`
缥缈孤鸿
  • 浏览: 42963 次
  • 性别: Icon_minigender_1
  • 来自: 大连
最近访客 更多访客>>
社区版块
存档分类
最新评论

MFC OpenGL标签云 (转)

    博客分类:
  • C++
阅读更多
  初识标签云是在去年年末,一看到这个应用我就特别感兴趣。还记得08年在北京做Mobile应用的时候就在想,是不是可以通过某种方式做界面扩展,让相对狭小的手机屏幕只显示有效部分,而扩展部分可以在屏幕以外,通过某种方式将他们调到屏幕以内。后来证实做这种思考的人不只是我自己,因为现在划屏应用已经是移动终端的基本应用模式了。当时也想过能不能在纵向做界面延伸,让界面深入到屏幕里面,要知道那可是无限的空间,不过没有想到什么好的方式。见到标签云的那一刻,我知道这就是我想要的,所以当时我就决定用OpenGL模拟一下,然后拿出来和大家共同探讨,看看有没有可能做成一个更成熟些应用。不过过年回来工作比较忙,所以也就搁置了。这两天刚阶段性的完成一个项目,所以得了空可以写这篇博客。
        要实现功能就要先分析原理,通过使用和观察我觉得标签云的每一个标签都分布在一个球体上,球在视平面上的投影是一个圆,而整个球就根据鼠标和这个投影圆的位置关系不同而旋转。鼠标离圆心越远转速愉快,反之则越慢。球体旋转是围绕一根通过球心且与视平面平行的转轴进行的,鼠标和投影圆圆心的位置关系同样控制者转轴的方向,那就是转轴垂直于投影圆圆心和鼠标的连线。最后一点,旋转过程总是迎着鼠标进行。
        知道了基本原理就要开始分析算法了,实现三维空间用OpenGL这自不必说,我曾经写过一篇日志《OpenGL控件》介绍了一个内置OpenGL基本框架环境的自定义控件,这次就是极基于这个控件的一个扩展应用。我还曾经在《三维向量类》一文中介绍过我自己写的一个进行三维程序设计时很实用的向量类CVector,当然这次建模还是要依靠它。唯一的问题是OpenGL对于中文支持的不好,有没有什么方法可以方便的显示中文呢?我这里采用的方法是在内存中生成一张文字的贴图,然后用Alpha混合的方式赋予一个plan,这样就可以利用系统字库在OpenGL中显示各种类型丰富的文字了。好了,主要问题都解决了,开始写代码。
        首先定义一个结构体来代表标签元中的一个标签:
 
typedef struct	tagTAGNODE
{
	CVector		m_vtrPos;	// 标签位置
	float		m_fWidth,	// 标签长
				m_fHeight;	// 标签宽
	UINT		m_uTexture; 	// 贴图号
}CloudTag, *lpCloudTag;     

   然后在COpenGLCtrl里维护一个CloudTag数组用来管理所有标签,也就是整个云。函数AddCloud用来添加一个标签,其代码如下:
 view plaincopyprint?void COpenGLCtrl::AddCloud(CString strName, COLORREF clrText, CString strFontName, int nPointSize, int nWeight, UINT uCharset)  
{  
    int         nMode;  
    CSize       sizeText;  
    CRect       rectTag;  
    CBitmap     bitmapTemp, *pOldBitmap;  
    CFont       fontTag, *pOldFont;  
    COLORREF    clrOld;  
    LOGFONT     lf;  
    CDC*        pDC         = GetDC();  
    CDC*        pMemDC      = new CDC;  
    lpCloudTag  pCloudTag   = new CloudTag;  
    int         nExtend     = 5;  
    float       fTemp;  
  
  
    //设置字体   
    memset(&lf, 0, sizeof(LOGFONT));  
  
    //设置字体样式   
    wcscpy_s(lf.lfFaceName, strFontName);  
    lf.lfHeight  = nPointSize;  
    lf.lfWeight  = nWeight;  
    lf.lfCharSet = uCharset;  
  
    fontTag.CreateFontIndirect(&lf);  
  
    //创建位图内存   
    pMemDC->CreateCompatibleDC(pDC);  
    pOldFont    = pMemDC->SelectObject(&fontTag);  
    nMode       = pMemDC->SetBkMode(TRANSPARENT);  
    clrOld      = pMemDC->SetTextColor(clrText);  
  
    sizeText    = pMemDC->GetTextExtent(strName, strName.GetLength());  
    pCloudTag->m_fWidth      = float(sizeText.cx+nExtend)/40;  
    pCloudTag->m_fHeight = float(sizeText.cy+nExtend)/40;  
    rectTag.SetRect(0, 0, sizeText.cx+nExtend, sizeText.cy+nExtend);  
  
    bitmapTemp.CreateCompatibleBitmap(pDC, rectTag.Width(), rectTag.Height());  
    pOldBitmap  = pMemDC->SelectObject(&bitmapTemp);  
  
    //填充客户区   
    pMemDC->DrawText(strName, strName.GetLength(), rectTag, DT_SINGLELINE|DT_CENTER|DT_VCENTER);  
    pMemDC->SetBkMode(nMode);  
    pMemDC->SelectObject(pOldFont);  
    pMemDC->SelectObject(pOldBitmap);  
    pMemDC->SetTextColor(clrOld);  
    delete  pMemDC;  
  
    BITMAP      bmData;  
    bitmapTemp.GetBitmap(&bmData);  
    unsigned char*  pData   = new unsigned char[bmData.bmWidthBytes*bmData.bmHeight];  
    bitmapTemp.GetBitmapBits(bmData.bmWidthBytes*bmData.bmHeight, pData);  
    for(int i=0; i<bmData.bmWidth; i++)  
    {  
        for(int j=0; j<bmData.bmHeight; j++)  
        {  
            if(pData[i*4+j*bmData.bmWidthBytes]!=0 || pData[i*4+j*bmData.bmWidthBytes+1]!=0 || pData[i*4+j*bmData.bmWidthBytes+2]!=0)  
                pData[i*4+j*bmData.bmWidthBytes+3]=255;  
        }  
    }  
    glGenTextures(1, &pCloudTag->m_uTexture);  
    glBindTexture(GL_TEXTURE_2D, pCloudTag->m_uTexture);  
    gluBuild2DMipmaps(GL_TEXTURE_2D, 4, bmData.bmWidth, bmData.bmHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);  
  
    delete  pData;  
  
    fTemp   = (rand()%50)/10.0f+3;  
    pCloudTag->m_vtrPos  = CVector(0, 0, fTemp);  
    fTemp   = (rand()%360-180)/360.0f;  
    pCloudTag->m_vtrPos.Rotate(fTemp, CVector(1, 0, 0));  
    fTemp   = (rand()%360-180)/360.0f;  
    pCloudTag->m_vtrPos.Rotate(fTemp, CVector(0, 1, 0));  
    fTemp   = (rand()%360-180)/360.0f;  
    pCloudTag->m_vtrPos.Rotate(fTemp, CVector(0, 0, 1));  
    m_tcDemo.Add(pCloudTag);  
}  

void COpenGLCtrl::AddCloud(CString strName, COLORREF clrText, CString strFontName, int nPointSize, int nWeight, UINT uCharset)
{
	int			nMode;
	CSize		sizeText;
	CRect		rectTag;
	CBitmap		bitmapTemp, *pOldBitmap;
	CFont		fontTag, *pOldFont;
	COLORREF	clrOld;
	LOGFONT		lf;
	CDC*		pDC			= GetDC();
	CDC*		pMemDC		= new CDC;
	lpCloudTag	pCloudTag	= new CloudTag;
	int			nExtend		= 5;
	float		fTemp;


	//设置字体
	memset(&lf, 0, sizeof(LOGFONT));

	//设置字体样式
	wcscpy_s(lf.lfFaceName, strFontName);
	lf.lfHeight	 = nPointSize;
	lf.lfWeight  = nWeight;
	lf.lfCharSet = uCharset;

	fontTag.CreateFontIndirect(&lf);

	//创建位图内存
	pMemDC->CreateCompatibleDC(pDC);
	pOldFont	= pMemDC->SelectObject(&fontTag);
	nMode		= pMemDC->SetBkMode(TRANSPARENT);
	clrOld		= pMemDC->SetTextColor(clrText);

	sizeText	= pMemDC->GetTextExtent(strName, strName.GetLength());
	pCloudTag->m_fWidth		= float(sizeText.cx+nExtend)/40;
	pCloudTag->m_fHeight	= float(sizeText.cy+nExtend)/40;
	rectTag.SetRect(0, 0, sizeText.cx+nExtend, sizeText.cy+nExtend);

	bitmapTemp.CreateCompatibleBitmap(pDC, rectTag.Width(), rectTag.Height());
	pOldBitmap	= pMemDC->SelectObject(&bitmapTemp);

	//填充客户区
	pMemDC->DrawText(strName, strName.GetLength(), rectTag, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
	pMemDC->SetBkMode(nMode);
	pMemDC->SelectObject(pOldFont);
	pMemDC->SelectObject(pOldBitmap);
	pMemDC->SetTextColor(clrOld);
	delete	pMemDC;

	BITMAP		bmData;
	bitmapTemp.GetBitmap(&bmData);
	unsigned char*	pData	= new unsigned char[bmData.bmWidthBytes*bmData.bmHeight];
	bitmapTemp.GetBitmapBits(bmData.bmWidthBytes*bmData.bmHeight, pData);
	for(int i=0; i<bmData.bmWidth; i++)
	{
		for(int j=0; j<bmData.bmHeight; j++)
		{
			if(pData[i*4+j*bmData.bmWidthBytes]!=0 || pData[i*4+j*bmData.bmWidthBytes+1]!=0 || pData[i*4+j*bmData.bmWidthBytes+2]!=0)
				pData[i*4+j*bmData.bmWidthBytes+3]=255;
		}
	}
	glGenTextures(1, &pCloudTag->m_uTexture);
	glBindTexture(GL_TEXTURE_2D, pCloudTag->m_uTexture);
	gluBuild2DMipmaps(GL_TEXTURE_2D, 4, bmData.bmWidth, bmData.bmHeight, GL_RGBA, GL_UNSIGNED_BYTE, pData);

	delete	pData;

	fTemp	= (rand()%50)/10.0f+3;
	pCloudTag->m_vtrPos	= CVector(0, 0, fTemp);
	fTemp	= (rand()%360-180)/360.0f;
	pCloudTag->m_vtrPos.Rotate(fTemp, CVector(1, 0, 0));
	fTemp	= (rand()%360-180)/360.0f;
	pCloudTag->m_vtrPos.Rotate(fTemp, CVector(0, 1, 0));
	fTemp	= (rand()%360-180)/360.0f;
	pCloudTag->m_vtrPos.Rotate(fTemp, CVector(0, 0, 1));
	m_tcDemo.Add(pCloudTag);


这个函数是生成标签的核心函数,在程序里标签表现出来的形式就是文本,所以函数支持对文本的几乎一切定制,这包括内容、颜色、字体、字号、样式等。函数首先会创建一个字体,然后根据文本内容需要的大小创建一个内存位图,将文字绘制于这个位图之上。准备好文字的位图就要通过它来制作材质了,这里有一个问题,位图是没有Alpha通道的,怎么办呢,有没有什么相对简单的方法处理呢?这里我的处理方法是这样的,看代码,通过GetBitmap获取位图信息然后观察bmData.bmWidth和bmData.bmWidthBytes的值,可以发现bmWidthBytes是bmWidth的四倍。原来位图在内存里是以RGBA的方式存储的,所以通过GetBitmapBits获取到的数据就是4位的。众所周知,内存位图创建时是黑色的,这里我认定标签文字不能为黑色,所以检测数据如果是黑色的就把Alpha设为透明,不是就设为不透明,然后创建贴图。最后设置向量,在一个范围内随机生成一个长度做一个指向屏幕外的向量,在以x、y、z三个轴随机旋转一个角度,这样就完成了一个标签的建模。
        渲染的部分很简单,就是常规的OpenGL绘制,只不过加上了材质设置了Alpha透明。其实这个Demo做的比较粗糙,文字周围存在黑边,不过做这个例子不是特别追求表现所以也就没有特别处理,代码如下:


 view plaincopyprint?void COpenGLCtrl::OnPaint()   
{  
    CPaintDC    dc(this);  
  
    //绘背景色   
    COLORREF    clrBkgnd    = GetSysColor(COLOR_BTNFACE);  
    glClearColor(float(GetRValue(clrBkgnd))/255, float(GetGValue(clrBkgnd))/255, float(GetBValue(clrBkgnd))/255, 0.0f);  
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
  
    //设置场景坐标系   
    glLoadIdentity();  
    //设置观察点   
    gluLookAt(0, 0, 30, 0, 0, 0, 0, 1, 0);  
  
    INT_PTR nCount  = m_tcDemo.GetCount();  
    for(int i=0; i<nCount; i++)  
    {  
        lpCloudTag  pCloudTag   = m_tcDemo.GetAt(i);  
  
        glBindTexture(GL_TEXTURE_2D, pCloudTag->m_uTexture);  
        glEnable(GL_BLEND);  
        glEnable(GL_ALPHA_TEST);  
        glAlphaFunc(GL_GREATER, 0.1f);  
        glBegin(GL_QUADS);  
        glTexCoord2i(0, 0), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX-pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY+pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);  
        glTexCoord2i(1, 0), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX+pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY+pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);  
        glTexCoord2i(1, 1), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX+pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY-pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);  
        glTexCoord2i(0, 1), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX-pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY-pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);  
        glEnd();  
        glDisable(GL_ALPHA_TEST);  
        glDisable(GL_BLEND);  
  
    }  
  
    //翻页   
    SwapBuffers(m_pDC->m_hDC);  
}  

void COpenGLCtrl::OnPaint() 
{
	CPaintDC	dc(this);

	//绘背景色
	COLORREF	clrBkgnd	= GetSysColor(COLOR_BTNFACE);
	glClearColor(float(GetRValue(clrBkgnd))/255, float(GetGValue(clrBkgnd))/255, float(GetBValue(clrBkgnd))/255, 0.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	//设置场景坐标系
	glLoadIdentity();
	//设置观察点
	gluLookAt(0, 0, 30, 0, 0, 0, 0, 1, 0);

	INT_PTR	nCount	= m_tcDemo.GetCount();
	for(int i=0; i<nCount; i++)
	{
		lpCloudTag	pCloudTag	= m_tcDemo.GetAt(i);

		glBindTexture(GL_TEXTURE_2D, pCloudTag->m_uTexture);
		glEnable(GL_BLEND);
		glEnable(GL_ALPHA_TEST);
		glAlphaFunc(GL_GREATER, 0.1f);
		glBegin(GL_QUADS);
		glTexCoord2i(0, 0), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX-pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY+pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);
		glTexCoord2i(1, 0), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX+pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY+pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);
		glTexCoord2i(1, 1), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX+pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY-pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);
		glTexCoord2i(0, 1), glVertex3f(pCloudTag->m_vtrPos.m_fVectorX-pCloudTag->m_fWidth/2, pCloudTag->m_vtrPos.m_fVectorY-pCloudTag->m_fHeight/2, pCloudTag->m_vtrPos.m_fVectorZ);
		glEnd();
		glDisable(GL_ALPHA_TEST);
		glDisable(GL_BLEND);

	}

	//翻页
	SwapBuffers(m_pDC->m_hDC);
}   
     剩下的事情就是鼠标控制和动画实现了,由于我的向量类很好的支持了旋转功能,而且标签云建模就是通过向量实现的,所以这一步也就好说了。所有标签都是通过以原点为起点的向量定位的,所以转轴也是通过原点的在XOZ面上的向量。在OnMouseHover中计算状态和转速,然后在OnTimer里旋转每个标签的向量就是了,代码如下:
view plaincopyprint?LRESULT COpenGLCtrl::OnMouseHover(WPARAM wParam, LPARAM lParam)  
{  
    CRect   rectView;  
    CPoint  point;  
  
    GetWindowRect(rectView);  
    GetCursorPos(&point);  
  
    m_vtrRotate.SetVector(float(-point.x), float(point.y), 0, -float(rectView.right+rectView.left)/2, float(rectView.bottom+rectView.top)/2, 0);  
    m_vtrRotate.Rotate(-PI/2, CVector(0, 0, 1));  
  
    m_fAngle    = m_vtrRotate.GetMod()/2000;  
    return 1;  
}  

LRESULT COpenGLCtrl::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
	CRect	rectView;
	CPoint	point;

	GetWindowRect(rectView);
	GetCursorPos(&point);

	m_vtrRotate.SetVector(float(-point.x), float(point.y), 0, -float(rectView.right+rectView.left)/2, float(rectView.bottom+rectView.top)/2, 0);
	m_vtrRotate.Rotate(-PI/2, CVector(0, 0, 1));

	m_fAngle	= m_vtrRotate.GetMod()/2000;
	return 1;
}
[cpp] view plaincopyprint?void COpenGLCtrl::OnTimer(UINT_PTR nIDEvent)  
{  
    switch(nIDEvent)  
    {  
    case TIMER_MOVE:  
        {  
            if(m_fAngle==0)  
                return;  
  
            INT_PTR nCount  = m_tcDemo.GetCount();  
            for(int i=0; i<nCount; i++)  
            {  
                lpCloudTag  pCloudTag   = m_tcDemo.GetAt(i);  
                pCloudTag->m_vtrPos.Rotate(m_fAngle, m_vtrRotate);  
                Invalidate();  
            }  
        }break;  
    }  
  
    CWnd::OnTimer(nIDEvent);  
}  

void COpenGLCtrl::OnTimer(UINT_PTR nIDEvent)
{
	switch(nIDEvent)
	{
	case TIMER_MOVE:
		{
			if(m_fAngle==0)
				return;

			INT_PTR	nCount	= m_tcDemo.GetCount();
			for(int i=0; i<nCount; i++)
			{
				lpCloudTag	pCloudTag	= m_tcDemo.GetAt(i);
				pCloudTag->m_vtrPos.Rotate(m_fAngle, m_vtrRotate);
				Invalidate();
			}
		}break;
	}



CWnd::OnTimer(nIDEvent);
}        到此基本的功能就已经全部实现了,在我的资源里上传了这个Demo有兴趣朋友可以下载研究一下,有什么好的想法可以和我进一步交流。做这个东西,写这篇文章权当抛砖引玉,希望能给大家些灵感,从三维的角度作出有更好用户体验的界面设计。最后贴一个效果图,见笑见笑。
[img][/img]




转(http://blog.csdn.net/xianglitian/article/details/6590687)
分享到:
评论

相关推荐

    OpenGL实现标签云

    将OpenGL与MFC结合,可以在MFC应用中嵌入OpenGL的图形渲染功能,比如在这个案例中的标签云效果。 标签云通常用于显示大量标签或关键词,每个标签的大小和旋转角度可以反映其重要性或频率。在OpenGL中,我们可以利用...

    piaoyun.rar_VS_VS c++界面

    在描述中提到,“用vs做的飘动的云的特效,特别适合做应用程序的开始界面”,这表明开发者使用了VS的图形用户界面(GUI)和可能的图形库来创建动态效果,模拟云朵在屏幕上的飘动。这种特效可以通过动画技术和图像...

    win7修复本地系统工具

    win7修复本地系统工具

    《自动化专业英语》04-Automatic-Detection-Block(自动检测模块).ppt

    《自动化专业英语》04-Automatic-Detection-Block(自动检测模块).ppt

    《计算机专业英语》chapter12-Intelligent-Transportation.ppt

    《计算机专业英语》chapter12-Intelligent-Transportation.ppt

    西门子S7-1200博图平台下3轴伺服螺丝机程序解析与应用

    内容概要:本文详细介绍了基于西门子S7-1200博图平台的3轴伺服螺丝机程序。该程序使用SCL语言编写,结合KTP700组态和TIA V14及以上版本,实现了对X、Y、Z三个轴的精密控制。文章首先概述了程序的整体架构,强调了其在自动化控制领域的高参考价值。接着深入探讨了关键代码片段,如轴初始化、运动控制以及主程序的设计思路。此外,还展示了如何通过KTP700组态实现人机交互,并分享了一些实用的操作技巧和技术细节,如状态机设计、HMI交互、异常处理等。 适用人群:从事自动化控制系统开发的技术人员,尤其是对西门子PLC编程感兴趣的工程师。 使用场景及目标:适用于希望深入了解西门子S7-1200博图平台及其SCL语言编程特点的学习者;旨在帮助读者掌握3轴伺服系统的具体实现方法,提高实际项目中的编程能力。 其他说明:文中提供的代码示例和设计理念不仅有助于理解和学习,还能直接应用于类似的实际工程项目中。

    MATLAB仿真:非线性滤波器在水下长基线定位(LBL)系统的应用与比较

    内容概要:本文详细探讨了五种非线性滤波器(卡尔曼滤波(KF)、扩展卡尔曼滤波(EKF)、无迹卡尔曼滤波(UKF)、粒子滤波(PF)和变维卡尔曼滤波(VDKF))在水下长基线定位(LBL)系统中的应用。通过对每种滤波器的具体实现进行MATLAB代码展示,分析了它们在不同条件下的优缺点。例如,KF适用于线性系统但在非线性环境中失效;EKF通过雅可比矩阵线性化处理非线性问题,但在剧烈机动时表现不佳;UKF利用sigma点处理非线性,精度较高但计算量大;PF采用蒙特卡罗方法,鲁棒性强但计算耗时;VDKF能够动态调整状态维度,适合信标数量变化的场景。 适合人群:从事水下机器人(AUV)导航研究的技术人员、研究生以及对非线性滤波感兴趣的科研工作者。 使用场景及目标:①理解各种非线性滤波器的工作原理及其在水下定位中的具体应用;②评估不同滤波器在特定条件下的性能,以便为实际项目选择合适的滤波器;③掌握MATLAB实现非线性滤波器的方法和技术。 其他说明:文中提供了详细的MATLAB代码片段,帮助读者更好地理解和实现这些滤波器。此外,还讨论了数值稳定性问题和一些实用技巧,如Cholesky分解失败的处理方法。

    VMware-workstation-full-14.1.3-9474260

    VMware-workstation-full-14.1.3-9474260

    DeepSeek系列-提示词工程和落地场景.pdf

    DeepSeek系列-提示词工程和落地场景.pdf

    javaSE阶段面试题

    javaSE阶段面试题

    《综合布线施工技术》第5章-综合布线工程测试.ppt

    《综合布线施工技术》第5章-综合布线工程测试.ppt

    安川机器人NX100使用说明书.pdf

    安川机器人NX100使用说明书.pdf

    S7-1200 PLC改造M7120平面磨床电气控制系统:IO分配、梯形图设计及组态画面实现

    内容概要:本文详细介绍了将M7120型平面磨床的传统继电器控制系统升级为基于西门子S7-1200 PLC的自动化控制系统的过程。主要内容涵盖IO分配、梯形图设计和组态画面实现。通过合理的IO分配,确保了系统的可靠性和可维护性;梯形图设计实现了主控制逻辑、砂轮升降控制和报警逻辑等功能;组态画面则提供了友好的人机交互界面,便于操作和监控。此次改造显著提高了设备的自动化水平、运行效率和可靠性,降低了维护成本。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是熟悉PLC编程和控制系统设计的专业人士。 使用场景及目标:适用于需要进行老旧设备升级改造的企业,旨在提高生产设备的自动化水平和可靠性,降低故障率和维护成本。具体应用场景包括但不限于金属加工行业中的平面磨床等设备的控制系统改造。 其他说明:文中还分享了一些实际调试中的经验和技巧,如急停逻辑的设计、信号抖动的处理方法等,有助于读者在类似项目中借鉴和应用。

    chromedriver-linux64-136.0.7103.48.zip

    chromedriver-linux64-136.0.7103.48.zip

    IMG_20250421_180507.jpg

    IMG_20250421_180507.jpg

    《网络营销策划实务》项目一-网络营销策划认知.ppt

    《网络营销策划实务》项目一-网络营销策划认知.ppt

    Lianantech_Security-Vulnerabil_1744433229.zip

    Lianantech_Security-Vulnerabil_1744433229

    MybatisCodeHelperNew2019.1-2023.1-3.4.1.zip

    MybatisCodeHelperNew2019.1-2023.1-3.4.1

    《Approaching(Almost)any machine learning problem》中文版第13章(最后一章)

    【深度学习部署】基于Docker的BERT模型训练与API服务部署:实现代码复用与模型共享

    火车票订票系统设计与实现(代码+数据库+LW)

    摘  要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装火车票订票系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,火车票订票系统的有效运用可以帮助管理人员准确快速地处理信息。 火车票订票系统在对开发工具的选择上也很慎重,为了便于开发实现,选择的开发工具为Eclipse,选择的数据库工具为Mysql。以此搭建开发环境实现火车票订票系统的功能。其中管理员管理用户,新闻公告。 火车票订票系统是一款运用软件开发技术设计实现的应用系统,在信息处理上可以达到快速的目的,不管是针对数据添加,数据维护和统计,以及数据查询等处理要求,火车票订票系统都可以轻松应对。 关键词:火车票订票系统;SpringBoot框架,系统分析,数据库设计

Global site tag (gtag.js) - Google Analytics