作者:姜尔
目录
一、技术思路
二、主要代码
三、完整示例代码
四、运行结果展示
在SuperMap iDesktopX中可以通过【拓扑构网】、【制作专题图】等方式配置三维管网模型。但固定的软件操作偶尔会不满足于用于高自由处理使用的业务场景,因此SuperMap iObject Java的好处即可体现。使用组件产品自行开发,搭配功能实现功能组合,一键生成也成为众多人士心头好。
管网数据常见有原始数据为【三维线数据集】、【三维线数据集】与【三维点数据集】以及【网络数据集】。 如数据未构建网络数据集,需先行构网。因此, 使用SuperMap iObject Java构建管网模型基础技术思路为先行对原始数据构建网络数据集,然后制作【自定义专题图】配置风格,如管点模型符号,最后添加至【场景】浏览。
在SuperMap iObject Java范例程序中,也可以参考【场景操作与地下模式】中管点制作自定义专题图的示例代码,或者【三维专题图】示例。
构建网络数据集主要用到NetworkBuilder3D类。三维网络建模类。该类提供三维网络数据集的构建,以及为三维网络数据集创建流向等功能。
三维网络数据集是进行三维网络分析的数据基础。与二维的网络模型相同,三维的网络模型分为三维设施网络模型和三维交通网络模型;同样使用弧段和结点及二者的空间拓扑关系来描述网络。二者的根本区别在于三维网络模型使用(x,y,z)表达空间位置。
本类提供了三种构建网络数据集的方法(三个 buildNetwork 重载方法),满足在不同的数据基础之上构建三维网络数据集:
1.已有的三维点、线数据不需要打断,并具有表达点线拓扑关系的字段(对应网络数据集的弧段 ID、结点 ID、起始结点 ID 和 终止结点 ID),例如采集管点和管段来建立管网,可以使用buildNetwork方法;
2.仅由三维线数据集构建,可通过设置打断模式确定是否在线线相交处打断,详见 buildNetwork方法;
3.由三维点(可选)、线数据集共同构建,可通过设置打断模式确定是否在点线相交、线线相交处打断,详见 buildNetwork方法。
需要特别强调的是,用于构建三维网络数据集的数据必须具有相同的坐标系,否则构建失败。
使用buildNetwork接口构建三维网络数据集。可以设置保存的非系统字段及打断模式。该方法仅通过三维线数据集来构建三维网络,需要注意打断模式的设置:打断模式设置为 LINE_SPLIT_BY_POINT_AND_LINE时,在线线相交处打断并添加网络结点;打断模式设置为 NONE,不在任何位置打断,仅在线的两端点添加网络结点;不允许将打断模式设置为 LINE_SPLIT_BY_POINT,否则抛出异常。
主要代码可参考如下:
// 构建三维网络数据集
DatasetVector resultNetwork = NetworkBuilder3D.buildNetwork(
lineDataset, pointDataset, new String[] { "SymbolID", "LineWidth",
"color" }, new String[] { "Name", "RotationX", "RotationY" , "RotationZ" , "SymbolID" , "ScaleX" , "ScaleY" , "ScaleZ" , "NodeID" },
datasource, networkName,
NetworkSplitMode3D.LINE_SPLIT_BY_POINT_AND_LINE, 0.02);//打断模式指定为“线线打断,同时点打断线”
构建专题图,可以使用Theme3DCustom类。三维自定义专题图类,该类可以通过字段表达式来动态设置显示的风格。 可参考联机帮助文档(Online Help)此类查看详细说明:
主要代码可参考如下:
//网络数据集线图层设置专题图
Theme3DCustom Theme3DCustom=new Theme3DCustom();
Theme3DCustom.setAltitudeModeExpression("1");
Theme3DCustom.setLineSymbolIDExpression("964513");//设置线型符号
Theme3DCustom.setLineWidthExpression("1");//设置线型宽度
Theme3DCustom.setAltitudeModeExpression("1");//设置表示高度模式的字段表达式。字段值为0表示贴地高度模式,为1表示绝对高度模式,为2表示相对地面高度模式,为3表示相对地下高度模式。当字段值不为0或1或2或3时,采用默认字段值0,即采用贴地高度模式。
Layer3DDataset Layer3DDatasetline =layer3Ds.add(resultNetwork,Theme3DCustom,true,"Layer3DDatasetlineTheme3DCustom");//添加网络专题图图层
// 打开工作空间
Workspace workspace = new Workspace();
WorkspaceConnectionInfo info = new WorkspaceConnectionInfo();
info.setServer("D:\\supermap\\iobjectsjava\\1101\\supermap-iobjectsjava-11.1.0-22010-101668-win64-all-Bin\\GettingStarted\\Gettingstarted\\NetworkTheme3DCustom\\Pipe3D\\Pipe3D\\Pipe3D\\Pipe.smwu");
info.setType(WorkspaceType.SMWU);
System.out.println("是否打开工作空间:" + workspace.open(info));
// 打开数据源
Datasource datasource = workspace.getDatasources().get(0);
System.out.println("打开数据源别名为:" + datasource.getAlias() + " 数据源打开的状态:" + datasource.isOpened() + " 数据源是否以只读方式打开:" + datasource.isReadOnly());//打印查询其描述信息
// 获取数据集,用于构建三维网络数据集的三维线数据集和三维点数数据集
DatasetVector lineDataset = (DatasetVector) datasource.getDatasets().get("PipeLine3D");
DatasetVector pointDataset = (DatasetVector) datasource.getDatasets().get("PipePoint3D");
String networkName = datasource.getDatasets().getAvailableDatasetName("testnetwork");// 获取一个合法的名称作为结果网络数据集的名称
// 构建三维网络数据集
DatasetVector resultNetwork = NetworkBuilder3D.buildNetwork(
lineDataset, pointDataset, new String[] { "SymbolID", "LineWidth",
"color" }, new String[] { "Name", "RotationX", "RotationY" , "RotationZ" , "SymbolID" , "ScaleX" , "ScaleY" , "ScaleZ" , "NodeID" },
datasource, networkName,
NetworkSplitMode3D.LINE_SPLIT_BY_POINT_AND_LINE, 0.02);//打断模式指定为“线线打断,同时点打断线”
System.out.println("打开数据集名称为:" + resultNetwork.getName()+"数据集类型为:"+resultNetwork.getType());//打印查询其描述信息
//判断构网是否创建成功
if (datasource.getDatasets().get(networkName) == null) {
System.out.println("网络数据集创建失败");
} else {
System.out.println("网络数据集创建成功!"+" 数据集个数为:"+datasource.getDatasets().getCount());
//判断成功,输出数据集名称
Datasets Datasets =datasource.getDatasets();
String[] DatasetsCount = new String[Datasets.getCount()];
for (int i = 0; i < Datasets.getCount(); i++) {
DatasetsCount[i]=Datasets.get(i).getName();
}
System.out.println("结果数据源数据集名称为 = " + StringUtils.join(DatasetsCount,","));
}
//创建场景,设置场景控件
Scene sceneObject = new Scene(workspace);//返回三维地图场景(Scene)对象
sceneObject.open("Pipe3D");//通过名称打开工作空间中的地图
Atmosphere atmosphere = sceneObject.getAtmosphere();
atmosphere.setVisible(false);//大气不可见
Underground Underground=sceneObject.getUnderground();
Underground.setVisible(true);//地下可见
GlobalImage GlobalImage=sceneObject.getGlobalImage();
GlobalImage.setVisible(false);//地球底图不可见
sceneObject.setSceneType(SceneType.GLOBE);//设置三维场景的类型,选择球体模式(Globe)和平面模式(Flat)两种。
System.out.println("场景数量:" + workspace.getScenes().getCount() + "场景名称:" + sceneObject.getName());
//添加图层
Layer3Ds layer3Ds = sceneObject.getLayers();
System.out.println("场景中原有图层数量:" + layer3Ds.getCount());//打印数据集名称
//线专题图
Theme3DCustom Theme3DCustom=new Theme3DCustom();
Theme3DCustom.setAltitudeModeExpression("1");
Theme3DCustom.setLineSymbolIDExpression("964513");//设置线型符号
Theme3DCustom.setLineWidthExpression("1");//设置线型宽度
Theme3DCustom.setAltitudeModeExpression("1");//设置表示高度模式的字段表达式。字段值为0表示贴地高度模式,为1表示绝对高度模式,为2表示相对地面高度模式,为3表示相对地下高度模式。当字段值不为0或1或2或3时,采用默认字段值0,即采用贴地高度模式。
Layer3DDataset Layer3DDatasetline =layer3Ds.add(resultNetwork,Theme3DCustom,true,"Layer3DDatasetlineTheme3DCustom");//添加网络专题图图层
Layer3DDatasetline.updateData();
sceneControl.getScene().refresh();
System.out.println(" 添加线专题图刷新三维场景");
//点专题图
Theme3DCustom Theme3DCustompoint=new Theme3DCustom();
Theme3DCustompoint.setAltitudeModeExpression("1");//设置高度模式,绝对
Theme3DCustompoint.setMarkerSymbolIDExpression("54440");//设置点符号
Theme3DCustompoint.setMarker3DRotateXExpression("1");//X旋转
Theme3DCustompoint.setMarker3DRotateYExpression("1");//Y旋转
Theme3DCustompoint.setMarker3DRotateZExpression("1");//Z旋转
Theme3DCustompoint.setMarker3DScaleXExpression("10");//X缩放
Theme3DCustompoint.setMarker3DScaleYExpression("10");//Y缩放
Theme3DCustompoint.setMarker3DScaleZExpression("10");//Z缩放
Layer3DDataset Layer3DDatasetpoint =layer3Ds.add(resultNetwork.getChildDataset(),Theme3DCustompoint,true,"Layer3DDatasetpointTheme3DCustom");//添加网络子图层专题图
Layer3DDatasetpoint.updateData();
sceneControl.getScene().refresh();
System.out.println(" 添加点专题图刷新三维场景");
System.out.println("场景中现有图层数量:" + layer3Ds.getCount());//打印数据集名称