三维场景中如何实现交互
一、介绍
MapGIS Objects SDK: 是一款组件式地理信息开发平台,提供全空间数据存储、管理、显示、编辑、查询、分析、制图输出等二三维一体化核心 GIS 功能,提供 C++、.NET、Java、Python 等开发资源,接口简单易用,性能优越,具备跨平台开发能力。
本篇内容将知道您如何使用MapGIS Objects SDK、MapGIS Desktop SDK实现在三维场景中如何实现模型的捕捉功能。
二、开发环境
| 软件 | 版本 | 下载地址 | 说明 |
|---|---|---|---|
| MapGIS 10 x64 All In One SDK for Windows | 10.7 | 开发包下载地址 | MapGIS 提供的一款地理信息开发平台,包含 MapGIS Objects Java 面向 Java 开发环境的跨平台组件式 GIS 开发资源。 |
| MapGIS 开发授权 | \ | 开发授权下载地址 | MapGIS 针对开发者提供开发授权,下载开发包并安装后,还需要获取开发授权才能正常使用。 |
| IntelliJ IDEA | 2020.3 以上版本 | IDEA 下载地址 | 一款适用于 Java 专业开发的集成开发环境(IDE)。 |
| JDK | 1.8 | JDK 下载地址 | JDK 是 Java 语言的软件开发工具包,JDK 是整个 java 开发的核心,它包含了 JAVA 的运行环境(JVM+Java 系统类库)和 JAVA 工具。 |
三、应用场景及功能实现
在基于 MapGIS 二次开发库进行桌面端应用或插件开发的过程中,常常需要实现用户自定义的交互功能。例如:交互式绘制轨迹、绘制任意多边形实现地理要素选取、三维空间测量等场景,都离不开对用户鼠标操作的响应与图形的动态绘制。为了实现这类交互逻辑,MapGIS 提供了强大的底层交互支持机制。开发者可以通过继承 G3DBaseTool 基类,重写其事件处理方法,来自定义交互行为。该类封装了三维场景中的鼠标按下、移动、抬起等核心事件,是构建自定义三维交互工具的基础。本文将以"在三维场景中交互式绘制并添加一个面状几何模型"为例,详细介绍如何基于 G3DBaseTool 实现自定义交互流程。通过本示例,用户将能够清晰掌握 MapGIS 三维开发中交互工具的设计思路与实现机制,为后续开发更复杂的三维交互功能(如拉框查询、动态建模、路径绘制等)打下坚实基础。相关 API 的详细说明可参考MapGIS Objects Java 的开发入门文档,api 文档参考 MapGIS Objects Java API。
1.实现交互绘制工具
publicclassInteractDrawToolextendsG3DBaseTool{privateDots3Ddots3D;privateGraphics3Dgraphics3D;publicCreateSurface(SceneControlsceneControl){super(sceneControl);this.dots3D=newDots3D();}@Overridepublicvoidstart(){this.sceneControl.enableInputTool(false);this.sceneControl.setCursor(Cursor.CROSSHAIR);super.start();}@Overridepublicvoidstop(){super.stop();this.clearTool();this.sceneControl.setCursor(Cursor.DEFAULT);this.sceneControl.enableInputTool(true);}@OverridepublicbooleanonMouseDbClick(MouseEvente){if(e.getButton()==MouseButton.PRIMARY){Dot3Ddot3D=newDot3D();booleanpicked=this.sceneControl.wpToLp((int)e.getX(),(int)e.getY(),dot3D);if(!picked){returnfalse;}this.dots3D.append(dot3D);}elseif(e.getButton()==MouseButton.SECONDARY){if(this.dots3D.size()>=2){Dot3Ddt0=this.dots3D.get(0);if(this.dots3D.size()==2){Dots3DnewDts=newDots3D();Dot3Ddt2=this.dots3D.get(1);Dot3Ddt1=newDot3D(dt0.getX(),dt2.getY(),dt0.getZ());Dot3Ddt3=newDot3D(dt2.getX(),dt0.getY(),dt0.getZ());newDts.append(dt0);newDts.append(dt1);newDts.append(dt2);newDts.append(dt3);this.dots3D=newDts.clone();}this.dots3D.append(dt0);Scenescene=this.sceneControl.getMapGISScene();if(scene==null){returnfalse;}List<Map3DLayer>layers=sceneControl.getMapGISScene().getEditLayer(EditLayerType.Surface,SelectLayerControl.Visible);if(layers.size()==0){returnfalse;}GeoVarLinevarLine=newGeoVarLine(this.dots3D);GeoMultiLinemultiLine=newGeoMultiLine();multiLine.append(varLine);GeoPolygonpolygon=newGeoPolygon();polygon.append(multiLine);GeoAnySurfacesurface=newGeoAnySurface();GeoModelCommon.createAnySurface(surface,this.dots3D,null,null,0,null);Map3DLayerlayer=layers.get(0);SFeatureClssfcls=(SFeatureCls)layer.getData();if(sfcls==null){returnfalse;}SurfaceInfosurInfo=newSurfaceInfo();surInfo.setFillClr(3);longoid=sfcls.append(surface,null,surInfo);this.sceneControl.updateSceneByModelState(scene,(short)layer.getLayerRenderIndex(),(int)oid,ModelOperType.AppendMdl);this.dots3D.clear();}this.clearTool();}returnsuper.onMouseDbClick(e);}@OverridepublicbooleanonMouseMoved(MouseEvente){if(this.dots3D.size()==0){returnfalse;}Dot3Ddot3D=newDot3D();booleanpicked=this.sceneControl.wpToLp((int)e.getX(),(int)e.getY(),dot3D);if(!picked){returnfalse;}Dots3DnewDots=newDots3D();newDots.append(this.dots3D);newDots.append(dot3D);this.drawPath(newDots,true);returnsuper.onMouseMoved(e);}/** * 清除数据 */privatevoidclearTool(){if(this.graphics3D!=null){this.graphics3D.removeAll();this.sceneControl.deleteGraphics(this.graphics3D);this.graphics3D=null;}}/** * 绘制路径 * * @param pathDots * @param clear */privatevoiddrawPath(Dots3DpathDots,booleanclear){if(clear){this.clearTool();}if(pathDots==null||pathDots.size()<=1){return;}if(this.graphics3D==null){this.graphics3D=this.sceneControl.createGraphics();}Dots3DvirtualDots=newDots3D();Dot3Ddt0=pathDots.get(0);virtualDots.append(dt0);if(pathDots.size()<=2){Dots3DnewDts=newDots3D();Dot3Ddt2=pathDots.get(1);Dot3Ddt1=newDot3D(dt0.getX(),dt2.getY(),dt0.getZ());Dot3Ddt3=newDot3D(dt2.getX(),dt0.getY(),dt0.getZ());newDts.append(dt0);newDts.append(dt1);newDts.append(dt2);newDts.append(dt3);pathDots=newDts.clone();virtualDots.append(dt2);}elseif(pathDots.size()==3){Dots3DnewDts=newDots3D();Dot3Ddt2=pathDots.get(1);Dot3Ddt1=newDot3D(dt0.getX(),dt2.getY(),dt0.getZ());Dot3Ddt3=newDot3D(dt2.getX(),dt0.getY(),dt0.getZ());newDts.append(dt0);newDts.append(dt1);newDts.append(dt2);newDts.append(dt3);newDts.append(dt0);virtualDots=newDts.clone();}else{virtualDots.append(pathDots.get(pathDots.size()-2));}pathDots.append(dt0);// region 折线Modelmodel=newModel();GeoMultiLinelines=newGeoMultiLine();lines.append(newGeoVarLine(pathDots));lines.append(newGeoVarLine(virtualDots));model.addPolyLine(lines);LinInfo3DlinInfo=newLinInfo3D();linInfo.setFillClr(6);model.setLine3DInfo(linInfo);this.graphics3D.append(model);// endregion}}