当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>Visual C++教程

GIS三维地景仿真设计

 为什么要使用服务应该程序呢?服务程序就像系统的一些服务一样,能够自动地启动,并执行相应的操作;而且因为服务程序的在层次上和一般的应用程序不同,其能够在系统启动时就自动地运行,而不像一般的应用程序那样一定要在登陆后才能运行,这些就是服务的一些好处了,如果你也想你的程序具有这样的功能,那么你就可以建立一个服务应用程序了。
      下面就跟着我一步一步地教你怎么去创建一个服务应用程序吧。
      本文主要介绍了OpenSCManager、CreateService、OpenService、ControlService、DeleteService、RegisterServiceCtrlHandler、SetServiceStatus、StartServiceCtrlDispatcher等操作服务程序的主要几个API的用法,具体的函数参数大家可以查阅MSDN。
      一、建立Win32 Application应用程序(当然你也可以建立其它的应用程序,但服务一般是没有用户界面的),并命名为ServiceTest。
      二、定义全局函数变量
    //定义全局函数变量
    void Init();
    BOOL IsInstalled();
    BOOL Install();
    BOOL Uninstall();
    void LogEvent(LPCTSTR pszFormat, ...);
    void WINAPI ServiceMain();
    void WINAPI ServiceStrl(DWORD dwOpcode);
    TCHAR szServiceName[] = _T("ServiceTest");
    BOOL bInstall;
    SERVICE_STATUS_HANDLE hServiceStatus;
    SERVICE_STATUS status;
    DWORD dwThreadID;
      三、添加Init初始化函数
      这里主要是设置服务句柄和状态。
    hServiceStatus = NULL;
    status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    status.dwCurrentState = SERVICE_STOPPED;
    tatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    status.dwWin32ExitCode = 0;
    status.dwServiceSpecificExitCode = 0;
    status.dwCheckPoint = 0;
    status.dwWaitHint = 0;
      四、添加安装和删除服务函数
      这里主要是用到了五个函数OpenSCManager、CreateService、OpenService、ControlService、DeleteService。OpenSCManager用于打开服务控制管理器;CreateService用于创建服务;OpenService用于打开已有的服务,返回该服务的句柄;ControlService则用于控制已打开的服务状态,这里是让服务停止后才删除;DeleteService用于删除指定服务。
    BOOL Install();
    {
     //这里列出主要的两个函数,其它的可以在代码里找。
     //打开服务控制管理器
     OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     //创建服务
     
     SC_HANDLE hService = ::CreateService(
      hSCM, szServiceName, szServiceName,
      SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
      SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
      szFilePath, NULL, NULL, _T(""), NULL, NULL);
     ::CloseServiceHandle(hService);
     ::CloseServiceHandle(hSCM);
    }
    BOOL Uninstall();
    {
     //这里列出主要的两个函数,其它的可以在代码里找。
     //打开服务控制管理器
     OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     //打开服务
     OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);
     //停止服务
     ControlService(hService, SERVICE_CONTROL_STOP, &status);
     //删除服务
     DeleteService(hService);
     …
    }
     五、添加服务主线程函数和控制函数
      这里调用RegisterServiceCtrlHandler来注册服务的控制函数,这里要设置status.dwControlsAccepted为SERVICE_ACCEPT_STOP,否则你不能控制这个服务的状态。
    void WINAPI ServiceMain()
    {
     // Register the control request handler
     status.dwCurrentState = SERVICE_START_PENDING;
     status.dwControlsAccepted = SERVICE_ACCEPT_STOP;//这个要使用,否则你不能控制
     //注册服务控制
     hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);
     if (hServiceStatus == NULL)
     {
      LogEvent(_T("Handler not installed"));
      return;
     }
     SetServiceStatus(hServiceStatus, &status);
     status.dwWin32ExitCode = S_OK;
     status.dwCheckPoint = 0;
     status.dwWaitHint = 0;
     status.dwCurrentState = SERVICE_RUNNING;
     SetServiceStatus(hServiceStatus, &status);
     //模拟服务的运行,10后自动退出。应用时将主要任务放于此即可
     int i = 0;
     while (i < 10)
     {
      Sleep(1000);
      i++;
     }
     //
     status.dwCurrentState = SERVICE_STOPPED;
     SetServiceStatus(hServiceStatus, &status);
     LogEvent(_T("Service stopped"));
    }
      六、在主线程函数里注册控制函数和程序执行主体
    void WINAPI ServiceMain()
    {
     …
     //如上,这里主要是说明这就是程序的执行体
     //模拟服务的运行,10后自动退出。应用时将主要任务放于此即可
     int i = 0;
     while (i < 10)
     {
      Sleep(1000);
      i++;
     }
     …
    }
      七、在main函数里注册添加安装、删除、注册主函数
    int APIENTRY WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
     Init();
     dwThreadID = ::GetCurrentThreadId();
     SERVICE_TABLE_ENTRY st[] =
     {
      { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
      { NULL, NULL }
     };
     if (stricmp(lpCmdLine, "/install") == 0)
     {
      Install();
     }
     else if (stricmp(lpCmdLine, "/uninstall") == 0)
     {
      Uninstall();
     }
     else
     {
      if (!::StartServiceCtrlDispatcher(st))
      {
       LogEvent(_T("Register Service Main Function Error!"));
      }
     }
     return 0;
    }
      八、总结
      其它做一个服务程序并难,主要是懂得程序的执行体放于哪里?和注册程序的主函数和注册控制函数,如果这两个没有注册的话,你就程序就不知道如何去控制了。status.dwControlsAccepted = SERVICE_ACCEPT_STOP;这个也重要,如果你没有设置的话,那么服务就不会受你控制了。
      通过前面给出的五篇技术文章,已经围绕对地景的真实感三维仿真这一最终目标以DEM数字高程模型和OpenGL各种主要技术向读者简要介绍了OpenGL基本程序框架的一般搭建、对DEM数字高程模型的使用、对三维场景的建模、与地景模型的人机交互以及对雾化与纹理等高级技术的使用等一系列知识点。通过对本系列文章的阅读,读者不仅能够掌握一般的GIS三维仿真处理程序的基本设计思想和具体的处理过程,还能够结合具体的程序实例对其中用到的各种OpenGL技术有一个更深刻的认识。本文下面还要从应用的角度对前面开发出来的地景三维仿真程序进行介绍。
      示例程序介绍
      上图展示的应用程序界面即为根据前面5篇文章所介绍的内容而设计出来的"DEM数字高程网格数据三维地景仿真系统"软件。该软件提供了对DEM数据的管理功能、对显示模式的选择功能、漫游控制功能、地景设置功能、以及对环境和纹理的设置等主要功能。其中,对DEM数据的管理功能包括了对DEM数据的新建、打开、保存等常规功能也提供了对DEM网格间距的调整等特殊功能。这里主要用到的是在本系列第二篇文章中介绍过的对DEM数据使用的相关内容。
      对显示模式的选择功能主要提供了对正射投影和透视投影这两种投影方式的选择以及对以点、线、面三种建模方式的选择切换,这部分功能主要建立在本系列第三篇文章中介绍的相关内容基础上。除此之外,环境设置中的材质设置功能也是建立在该文章内容基础上的。
      为了能够提供方便的多视角、任意观察距离的实景观察仿真效果,这里除了提供包含旋转、平移和缩放等基本几何变换的鼠标、键盘全景漫游功能之外,还提供了对地景高差系数的控制功能,这部分功能的实现过程在第四篇文章中有详细的介绍。
      软件的雾化功能和纹理设置功能可以最大程度的为软件提供真实感地景仿真效果。尤其是纹理设置功能的提供可以使用户只通过更换同一地区不同用途的纹理位图而实现对同一个DEM数据资源的重复利用,能够充分利用其中的资源。这部分内容的实现过程主要体现在第五篇文章的相关论述中。现在读者不妨将前几篇文章重新阅读一番,并从整体上重新去把握,相信不难设计出类似的三维地景仿真程序。
      在工程中的应用
      上述示例程序仅仅是一个教学性质的通用示例程序,可以应用于各类GIS软件中。例如军事地形数字勘测侦察系统、电子沙盘仿真系统、全国各省地市区地形地貌全三维仿真系统、中小学地理教学互动课件等等许多方面。只需在原有基础上根据不同类型的应用添加特定的相关功能即可。上图给出的即为在此基础上实现的"全国各省地市区地形地貌全三维仿真系统"仿真出来的新疆昌吉地区三维地理地貌。从图中可以清晰的看出铁路、公路、山峦和城市的三维展示,而且可以根据用户的需要通过漫游、旋转和缩放等功能查看感兴趣区域的细部特征。如果添加适当的前期处理,甚至可以根据一幅普通的地图建立当地的三维仿真模型。这里限于篇幅仅大致介绍一下主要步骤:先将普通地图扫描成位图,然后通过矫正和配准处理形成标准矩形位图,接下来可以通过中值滤波等普通的图象处理算法消除扫描过程产生的噪声。最后,通过对所形成位图的均匀网格取样,从中抽取位于节点处的象素颜色值。由于在标准的地形地图中是以颜色来标识高程的,因此根据次颜色值是能够反过来计算出该点高程数据的,由这些高程数据不难建立DEM数字高程模型文件,并由此建立当地的三维地景模型。如果有必要,还可以将当地地图作为纹理进行贴图。
      另外一个应用是可以将通过大地测量等手段建立起来的某一地区高程模型与遥感卫星成像得到的该地区遥感图象有机的结合在一起。具体使用仍是以DEM数据作为三维建模的数据来源,卫星遥感图象在经过适当处理后作为纹理来使用。上图给出的即为此应用结果。其中右图为法国SPOT卫星PAN波段对我国某一地区的遥感成像结果;左图为经过三维建模后的场景。可以看出,通过建模,可以清晰而真实的观察当地的地理地貌,图中的机场等显著地表清晰可见。一般来说,将遥感图象与高程数据模型的综合使用更有助于汲取更大的信息量。
     与其他主流三维技术的比较
      OpenGL作为SGI公司推出的专业图形加速卡的图形软件应用程序接口,允许程序员对2D和3D几何形体进行描述并绘制到帧缓存。它的工作方式就如同一个状态机,可以通过各种状态和模式设置控制绘制过程,达到绘制要求。实际上,OpenGL已经成为首选的2D和3D开发环境。它是低层的API,具有与硬件无关的特征,因而具有很强的可移植性。厂商只要提供OpenGL扩展,就可以轻松实现硬件特有的功能。利用OpenGL扩展OpenGL实现者也可以添加新的处理算法。
      1995年至1996年,微软计划支持在Windows95上运行游戏,并把目标定为把市场扩展到被任天堂和世嘉控制的游戏领域。但是此时的微软并不打算使用已经在NT上提供的OpenGL技术而是收购了Rendermorphics,Ltd.并得到他的被称作RealityLab的3D API。经重新整理,微软发布了新的3D API--Direct3D。之后的一段时间,尽管D3D有很多问题而且不能像OpenGL那样被硬件厂商扩展,但是微软仍大力推行Direct3D并开始无限冻结OpenGL。Silicon Graphics和很多OpenGL用户都依赖OpenGL创新且高性能的技术,Silicon Graphics通过在1996年举行的SIGGRAPH会议上的一次演示证明了OpenGL至少和D3D一样快,从而有力驳倒了微软的市场论调。因为OpenGL是业界公认标准,比D3D功能丰富,而且图像质量要高一些,所以此次演示在计算机图形和游戏开发界引发了激烈的讨论。
      Doom的开发者John Carmack首先声明拒绝D3D,紧接着Chris Hecker在游戏开发杂志上发表了两套API的全面分析,并得出微软应放弃D3D的结论。游戏开发者先后两次向微软递交请愿书。第一次由56名首席游戏开发者要求微软发行OpenGL MCD驱动,但未成功,因为会让OpenGL与D3D竞争。第二次的公开信由254人签名开始,截止时达到1400人。微软的回答仍是重申旧市场立场。尽管请愿者清楚的要求两套API同等竞争以促进发展,微软却以增加D3D的投资、更加减少OpenGL的投资为回应。
      Silicon Graphics,Microsoft, HP,Intel达成协议联合开发下一代3D API--Fahrenheit。但不了了之,因为微软的打算是把OpenGL的技术用到D3D里并且以此之名驱除OpenGL的威胁(DirectX 8 Graphics即从技术上吸收了OpenGL的很多东西)。到目前为止,OpenGL依然是唯一能与微软单独控制的D3D对立的API,尽管Silicon Graphics不再以任何微软不能接受的方式推行OpenGL。游戏开发这是独立的,并且很多关键人物在用OpenGL,因此,硬件厂商正努力提高对其支持。D3D仍不能支持高端图像和专业应用,表面上好像D3D比OpenGL支持更多的功能,其实由于D3D不支持硬件扩展,如硬件全景阴影,硬件渲染顺序无关半透明材质等新技术根本无法使用,而D3D(特指D3D8)本身提供的功能只有一小部分能在使用HAL且硬件不支持时模拟,因此需要使用大量的代码分析硬件能力并采取不同策略。以上种种使得OpenGL依旧主宰着这片土地。
相关内容
赞助商链接