三维场景中如何实现交互
一、介绍
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.实现交互绘制工具
public class InteractDrawTool extends G3DBaseTool {
private Dots3D dots3D;
private Graphics3D graphics3D;
public CreateSurface(SceneControl sceneControl) {
super(sceneControl);
this.dots3D = new Dots3D();
}
@Override
public void start() {
this.sceneControl.enableInputTool(false);
this.sceneControl.setCursor(Cursor.CROSSHAIR);
super.start();
}
@Override
public void stop() {
super.stop();
this.clearTool();
this.sceneControl.setCursor(Cursor.DEFAULT);
this.sceneControl.enableInputTool(true);
}
@Override
public boolean onMouseDbClick(MouseEvent e) {
if (e.getButton() == MouseButton.PRIMARY) {
Dot3D dot3D = new Dot3D();
boolean picked = this.sceneControl.wpToLp((int) e.getX(), (int) e.getY(), dot3D);
if (!picked) {
return false;
}
this.dots3D.append(dot3D);
} else if (e.getButton() == MouseButton.SECONDARY) {
if (this.dots3D.size() >= 2) {
Dot3D dt0 = this.dots3D.get(0);
if (this.dots3D.size() == 2) {
Dots3D newDts = new Dots3D();
Dot3D dt2 = this.dots3D.get(1);
Dot3D dt1 = new Dot3D(dt0.getX(), dt2.getY(), dt0.getZ());
Dot3D dt3 = new Dot3D(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);
Scene scene = this.sceneControl.getMapGISScene();
if (scene == null) {
return false;
}
List<Map3DLayer> layers = sceneControl.getMapGISScene().getEditLayer(EditLayerType.Surface, SelectLayerControl.Visible);
if (layers.size() == 0) {
return false;
}
GeoVarLine varLine = new GeoVarLine(this.dots3D);
GeoMultiLine multiLine = new GeoMultiLine();
multiLine.append(varLine);
GeoPolygon polygon = new GeoPolygon();
polygon.append(multiLine);
GeoAnySurface surface = new GeoAnySurface();
GeoModelCommon.createAnySurface(surface, this.dots3D, null, null, 0, null);
Map3DLayer layer = layers.get(0);
SFeatureCls sfcls = (SFeatureCls) layer.getData();
if (sfcls == null) {
return false;
}
SurfaceInfo surInfo = new SurfaceInfo();
surInfo.setFillClr(3);
long oid = sfcls.append(surface, null, surInfo);
this.sceneControl.updateSceneByModelState(scene, (short) layer.getLayerRenderIndex(), (int) oid, ModelOperType.AppendMdl);
this.dots3D.clear();
}
this.clearTool();
}
return super.onMouseDbClick(e);
}
@Override
public boolean onMouseMoved(MouseEvent e) {
if (this.dots3D.size() == 0) {
return false;
}
Dot3D dot3D = new Dot3D();
boolean picked = this.sceneControl.wpToLp((int) e.getX(), (int) e.getY(), dot3D);
if (!picked) {
return false;
}
Dots3D newDots = new Dots3D();
newDots.append(this.dots3D);
newDots.append(dot3D);
this.drawPath(newDots, true);
return super.onMouseMoved(e);
}
/**
* 清除数据
*/
private void clearTool() {
if (this.graphics3D != null) {
this.graphics3D.removeAll();
this.sceneControl.deleteGraphics(this.graphics3D);
this.graphics3D = null;
}
}
/**
* 绘制路径
*
* @param pathDots
* @param clear
*/
private void drawPath(Dots3D pathDots, boolean clear) {
if (clear) {
this.clearTool();
}
if (pathDots == null || pathDots.size() <= 1) {
return;
}
if (this.graphics3D == null) {
this.graphics3D = this.sceneControl.createGraphics();
}
Dots3D virtualDots = new Dots3D();
Dot3D dt0 = pathDots.get(0);
virtualDots.append(dt0);
if (pathDots.size() <= 2) {
Dots3D newDts = new Dots3D();
Dot3D dt2 = pathDots.get(1);
Dot3D dt1 = new Dot3D(dt0.getX(), dt2.getY(), dt0.getZ());
Dot3D dt3 = new Dot3D(dt2.getX(), dt0.getY(), dt0.getZ());
newDts.append(dt0);
newDts.append(dt1);
newDts.append(dt2);
newDts.append(dt3);
pathDots = newDts.clone();
virtualDots.append(dt2);
} else if (pathDots.size() == 3) {
Dots3D newDts = new Dots3D();
Dot3D dt2 = pathDots.get(1);
Dot3D dt1 = new Dot3D(dt0.getX(), dt2.getY(), dt0.getZ());
Dot3D dt3 = new Dot3D(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 折线
Model model = new Model();
GeoMultiLine lines = new GeoMultiLine();
lines.append(new GeoVarLine(pathDots));
lines.append(new GeoVarLine(virtualDots));
model.addPolyLine(lines);
LinInfo3D linInfo = new LinInfo3D();
linInfo.setFillClr(6);
model.setLine3DInfo(linInfo);
this.graphics3D.append(model);
// endregion
}
}
1961

被折叠的 条评论
为什么被折叠?



