Qt项目-同步操作地球系统

项目介绍

1.简介

这是基于Qt+OSG的项目,可支持在局域网内多机器上同步进行操作地球(目前仅支持鼠标对球面的点击和缩放操作),可在球面上绘制点、线、面(可调整线宽),选择节点可对绘制的图形进行删除、撤销等操作,另外可在球面上展示特效(下雪,下雨,火焰等等),可在球表面上播放视频,可连接网络上的数据在球面展示。本项目已经开源到github,链接已经放在文末,有兴趣的童鞋可对本项目提出建议提交修改(bug,优化等),看到了我会第一时间进行反馈。😊
(目前仅支持Windows系统)

2.环境搭建

开发环境:
💻Windows10+VS2017+Qt5.12.3
🌏OpenSceneGraph-3.6.5+OSGEarth-2.10+CMake-3.22.1
编译参考教程链接已经放在文末尾,过程可能还有细微的不同,有问题可在评论区讨论。
注意:VS编译前后的版本一定要保持一致,不然可能出现各种莫名奇妙的问题

3.设计思路

  • 将OSGEarth嵌入到Qt的MainWindow当中,创建停靠窗口,在停靠窗口当中进行做绝大多数的功能,在底下的状态栏中以展示球面的经纬度坐标。
  • 在进行同步时所用的思路是:在球面上进行鼠标操作时,实际上,点击(缩放)并不能第一时间到达球体,而是通过一个中转的服务器程序到达,服务器程序功能目前非常简单,只负责接收和广播,这时,如不考虑丢包的情况,到达每个球体的操作的时序都是一致的。
  • 在使用网络数据时,为了防止没网的时候出现界面卡顿的情况使用了多线程加载。

4.部分源码

  • 中转服务器程序核心代码
#include <iostream>
#include"broadcaster.h"
#include"receiver.h"
int main()
{
	Broadcaster     BC;
	Receiver        RC;
	BC.setPort(static_cast<short int>(8101));
	RC.setPort(static_cast<short int>(8100));
	char *currentPtr;
	char *startPtr;
	//char *endPtr;
	int num = 1024;
	currentPtr = startPtr = new char[num];

	printf("服务器信息如下:\n");
	while (true)
	{
		RC.setBuffer(startPtr, 1024);
		unsigned int readsize = RC.sync();
		static int i = 0;
		//printf("缓存区数据的大小为%u,计数值为:%d\n", readsize,i++);
		BC.setBuffer(startPtr, 1024);
		BC.sync();	
	}
	return 0;
}
  • 控制绘制模式
bool CPickHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
	switch (ea.getEventType())
	{
	case osgGA::GUIEventAdapter::PUSH:
	{
		//std::cout << "handle:"<<ea.getX() << ":"<<ea.getY()<<std::endl;;
		//pick(ea.getX(), ea.getY());
		
		//drawDot(mLonLatAlt.x(), mLonLatAlt.y());
		//std::cout << "ml" << mLonLatAlt.x() << ":" << mLonLatAlt.y()<<std::endl;
		
		//std::cout << "button:" << ea.getButton()<<std::endl;

		int button = ea.getButton();
		
		if (button == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
		{
			
			//判断选择绘制类型
			if (mSelected==SelectedDraw::NONE)
			{
				pick(ea.getX(), ea.getY());
				if (m_oc->mViewerMode != OsgContainer::ViewerMode::STAND_ALONE)
				{
					m_oc->mOperaPacket._operaType = 0;
					m_oc->mOperaPacket._llaX = ea.getX();
					m_oc->mOperaPacket._llaY = ea.getY();
					
				}
				
				
			}
			else if (mSelected == SelectedDraw::DOT)
			{
				pick(ea.getX(), ea.getY());
				if(mIsPickObject)
				{ 
					drawDot(mLonLatAlt.x(), mLonLatAlt.y());

					if (m_oc->mViewerMode != OsgContainer::ViewerMode::STAND_ALONE)
					{
						m_oc->mOperaPacket._operaType = 1;
						
						m_oc->mOperaPacket._llaX = mLonLatAlt.x();
						m_oc->mOperaPacket._llaY = mLonLatAlt.y();
						
					}
					
				}
			}
			else if (mSelected==SelectedDraw::LINE)
			{ 
				
				pick(ea.getX(), ea.getY());
				if (mIsPickObject)
				{
				
					if (mLineN >= 2)
					{		
						
						mLineVec->push_back(mLonLatAlt);
						drawLine();	

						mLineXArr[1] = mLonLatAlt.x();
						mLineYArr[1] = mLonLatAlt.y();

						if (m_oc->mViewerMode != OsgContainer::ViewerMode::STAND_ALONE)
						{
							m_oc->mOperaPacket._operaType = 2;

							for (int i = 0; i < 2; i++)
							{
								m_oc->mOperaPacket._llaXArr[i] = mLineXArr[i];
								m_oc->mOperaPacket._llaYArr[i] = mLineYArr[i];
							}
							m_oc->mOperaPacket._llaSize = 2;
						}
					}
					else
					{
						mLineVec->push_back(mLonLatAlt);
						mLineN++;

						mLineXArr[0] = mLonLatAlt.x();
						mLineYArr[0] = mLonLatAlt.y();
					}

					
				}
			}
			else if(mSelected == SelectedDraw::TRIANGLES)
			{
				pick(ea.getX(), ea.getY());
				if (mIsPickObject)
				{

					if (mLineN>=3)
					{
						mLineVec->push_back(mLonLatAlt);
						drawTriangles();

						mLineXArr[2] = mLonLatAlt.x();
						mLineYArr[2] = mLonLatAlt.y();

						if (m_oc->mViewerMode != OsgContainer::ViewerMode::STAND_ALONE)
						{
							m_oc->mOperaPacket._operaType = 3;

							for (int i = 0; i < 3; i++)
							{
								m_oc->mOperaPacket._llaXArr[i] = mLineXArr[i];
								m_oc->mOperaPacket._llaYArr[i] = mLineYArr[i];
							}
							m_oc->mOperaPacket._llaSize = 3;
						}
				
					}
					else
					{
						mLineVec->push_back(mLonLatAlt);
						mLineN++;

						int n = mLineN - 2;
						mLineXArr[n] = mLonLatAlt.x();
						mLineYArr[n] = mLonLatAlt.y();
					}
					
				}
			}
			else if (mSelected == SelectedDraw::PARALLELOGRAM)
			{
				pick(ea.getX(), ea.getY());
				if (mIsPickObject)
				{
				
					if (mLineN >= 4)
					{
						drawParallelogram();
					}
					else
					{
						mLineVec->push_back(mLonLatAlt);
						mLineN++;
					}
				}
			}
			else //无选择时
			{
				return false;
			}
			
		}
		else if (button == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
		{
	
			reDrawXXX();
			pick(ea.getX(), ea.getY());

			
			
		}
		return false;
	}
	case osgGA::GUIEventAdapter::MOVE:
	{

	}
	case osgGA::GUIEventAdapter::DRAG:
	{
		
	}
	case osgGA::GUIEventAdapter::RELEASE:
	{
		int button = ea.getButton();
		if (button == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
		{
			
			m_oc->mOperaPacket._llaX = ea.getX();
			m_oc->mOperaPacket._llaY = ea.getY();
			
			
		}
		
	}
	default:
		return false;
	}

}

功能演示

  • 主要(核心)功能

    1.同步旋转
    请添加图片描述

    2.同步绘制点线面
    请添加图片描述

    3.删除撤销重做
    请添加图片描述

  • 其它功能

    1.播放视频
    请添加图片描述
    2.几个特效显示特效
    请添加图片描述

    3.连接网络数据
    请添加图片描述

地址

1.源码地址

主程序:https://github.com/whyzzd/OSG

2.编译OSG参考博文地址

osgEarth源码编译(Win10+VS2019+OSG3.6.5+osgEarth2.10.0)
OSG源码编译
OSG教程::基于VS2013的64位OSGEarth编译
osg、osgearth教程VS2017_aspiretop的博客-程序员资料
再次提醒:最后使用的VS版本一定要和编译出来的库版本保持一致

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值