SuperMap iClient3D for WebGL与iObjects Java结合实现前端动态绘制面与体的布尔运算

文章目录


前言

在三维城市道路设计中,我们时常会模拟物体通过限高路段是是否能正常通过,需要得到不同的通过物体是否存在超过限高的现象,超高多少,如超过,应该对通过物,裁剪多高才能正常通过。已上需求单靠前端的话难以做到,因此我们需要结合后端服务来实现。


一、前端构建通过物以及裁剪面

javascript 复制代码
			entity = viewer.entities.add({
				name: '带边框的绿色圆锥',
				position: SuperMap3D.Cartesian3.fromDegrees(116.0636726109858, 30.032487387912454, 1600),
				cylinder: {
					length: 2000,
					topRadius: 0.0,
					bottomRadius: 600.0,
					material: SuperMap3D.Color.BLUE.withAlpha(0.5),
					// outline: true,
					// outlineColor: SuperMap3D.Color.DARK_GREEN
				}
			});

			viewer.flyTo(entity)
			// 定义坐标点数组(经度,纬度,高度)
			const positions = [
				116.03202241972726, 30.028348734853576, 1500,
				116.04873386096398, 30.01183763716355, 2000,
				116.09021417949586, 30.033660215083376, 1800,
				116.07617627250876, 30.058336989847938, 1200
			];

			// 创建实体面
			const polygonEntity = viewer.entities.add({
				name: '空中三维面',
				polygon: {
					hierarchy: new SuperMap3D.PolygonHierarchy(
						SuperMap3D.Cartesian3.fromDegreesArrayHeights(positions)
					),
					material: SuperMap3D.Color.RED.withAlpha(0.5),
					// height: 0,  // 设置为0表示完全使用坐标中的高度值
					// extrudedHeight: 0,  // 设置为0表示不额外拉伸
					perPositionHeight: true,  // 关键!启用每个顶点独立高度
					// closeTop: true,
					// closeBottom: false,  // 不封闭底部,让面悬浮在空中
					// outline: true,
					// outlineColor: SuperMap3D.Color.WHITE,
					// outlineWidth: 2
				}
			});

二、后端创建接口实现布尔运算

1、根据前端传过来的参数构建体

java 复制代码
//获取前端传过来的三维面
        String points = request.getParameter("points");
        //解析三维面节点字符串
        JSONArray jsonArray = new JSONArray(points);
        String[][] strings = new String[jsonArray.length()][3];
        // 遍历 JSONArray 并存入 String[]
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONArray jsonArray_child = new JSONArray(jsonArray.getString(i));

            strings[i][0] = jsonArray_child.getString(0);
            strings[i][1] = jsonArray_child.getString(1);
            strings[i][2] = jsonArray_child.getString(2);
        }
        //构造三维点集 用于构造三维面
        Point3Ds point3Ds = new Point3Ds();

        for (int i = 0; i < strings.length; i++) {
            Point3D point3D = new Point3D();
            point3D.setX(Double.parseDouble(strings[i][0]));
            point3D.setY(Double.parseDouble(strings[i][1]));
            point3D.setZ(Double.parseDouble(strings[i][2]));
            point3Ds.add(point3D);
        }

        //拉伸闭合体参数
        EnvelopParameter envelopParameter = new EnvelopParameter();
        envelopParameter.setLonLat(true);
        envelopParameter.setStretchHeight(-3000);

        //初始化工作空间
        workspace = new Workspace();

        //创建内存型数据源
        DatasourceConnectionInfo info = new DatasourceConnectionInfo();
        info.setEngineType(EngineType.UDB);
        info.setServer(":memory:");
        Datasource datasource = workspace.getDatasources().create(info);

        //创建一个模型数据集
        DatasetVectorInfo datasetvectorinfo = new DatasetVectorInfo();
        datasetvectorinfo.setType(DatasetType.MODEL);
        datasetvectorinfo.setName("NewModel_1");
        DatasetVector datasetVector_result = datasource.getDatasets().create(datasetvectorinfo);
        datasetVector_result.setPrjCoordSys(new PrjCoordSys(4490));
//        DatasetVector datasetVector_result = (DatasetVector) datasource.getDatasets().get("NewModel_1");
        //获取模型数据集的记录集
        Recordset recordset = datasetVector_result.getRecordset(false, CursorType.DYNAMIC);
        System.out.println("recordsetCount:"+recordset.getRecordCount());

        recordset.edit();
        recordset.moveLast();
        //构造三维面
        GeoRegion3D geoRegion3D = new GeoRegion3D();
        geoRegion3D.addPart(point3Ds);
        //三维面几何对象构建闭合体,用于跟通过物模型做运算
        ArrayList<GeoModel3D> arrayList = ModelBuilder3D.envelop(geoRegion3D,  envelopParameter);
        for (int i = 0; i < arrayList.size(); i++) {
            recordset.addNew(arrayList.get(i));
            recordset.moveNext();
        }

        System.out.println("recordsetCount:"+recordset.getRecordCount());

        //获取前端传过来的通过物构造参数
        Double positionX = Double.valueOf(request.getParameter("x"));
        Double positionY = Double.valueOf(request.getParameter("y"));
        Double positionZ = Double.valueOf(request.getParameter("z"));
        Double bottomRadius = Double.valueOf(request.getParameter("bottomRadius"));
        Double height = Double.valueOf(request.getParameter("height"));

        //构造圆锥体通过物
        GeoCone geoCone = new GeoCone();
        geoCone.setPosition(new Point3D(positionX,positionY,positionZ));
        geoCone.setBottomRadius(bottomRadius);
        geoCone.setHeight(height);

2、体和面构建完成之后进行布尔运算

java 复制代码
//获取数据集中需要做运算的模型对象
        Recordset recordset_result = datasetVector_result.query("SmID=1",CursorType.DYNAMIC);
        GeoModel3D geoModel3D = (GeoModel3D) recordset_result.getGeometry();
        System.out.println("通过物模型最高点高程:"+(geoCone.getHeight()+geoCone.getPosition().getZ()));
        //进行布尔运算求差
        Geometry3D geometry3D = BooleanOperator3D.erase(geoCone,geoModel3D);
        if (geometry3D.isEmpty()){
            return "该物体没有相交";
        }
        geometry3D.setPosition(new Point3D(positionX,positionY,positionZ));
        if(!geometry3D.isEmpty()){
            System.out.println("布尔运算擦除成功!!!");
        }

3、布尔元算结果数据保存

java 复制代码
		ModelFileSetting fileSetting = new ModelFileSetting();
        String modelPath = "E:\\工作\\iserver\\supermap-iserver-2025u1-windows-x64-deploy\\webapps\\iserver\\";
        String name = Math.random()+".s3m";
        fileSetting.setFilePath(modelPath+name);
        boolean isConvert = ModelConvertor.toFile(((GeoModel3D) geometry3D).getModel(),fileSetting);

4、计算通过物超高高度

java 复制代码
//获取模型三维底面,用于计算超高高度
        GeoRegion geoRegion = ModelBuilder3D.planeProjection2D((GeoModel3D) geometry3D,new Plane());

        ArrayList<Geometry> arrayList_region = new ArrayList<>();
        arrayList_region.add(geoRegion);
        MatchParameter matchParameter = new MatchParameter();
        matchParameter.setAttach(AttachOption.BOTTOM);
        matchParameter.setSampleDistance(0.1);

        ArrayList<Geometry3D> arrayList_region3d = ModelBuilder3D.geometryMatch((GeoModel3D)geometry3D,arrayList_region,matchParameter);
        GeoRegion3D  region3D = (GeoRegion3D) arrayList_region3d.get(0);
        if(region3D.getPartCount()<0){
            return "三维面对象为0";
        }
        double overMaxZ = region3D.getPart(0).getItem(0).getZ();
        double overMinZ = region3D.getPart(0).getItem(0).getZ();



        for (int i = 0; i < region3D.getPartCount(); i++) {
            for (int j = 0; j < region3D.getPart(i).getCount(); j++) {
                double currentZ = region3D.getPart(i).getItem(j).getZ();
                if (currentZ > overMaxZ) {
                    overMaxZ = currentZ;
                }
                if (currentZ < overMinZ) {
                    overMinZ = currentZ;
                }
            }
        }
        overMinZ = (((GeoModel3D)geometry3D).getMaxZ()-overMinZ);
        overMaxZ = (((GeoModel3D)geometry3D).getMaxZ()-overMaxZ);
        System.out.println("通过物体最高超高:"+overMinZ+"米");
        System.out.println("通过物体最低超高:"+overMaxZ+"米");

5、运算结果返回前端

java 复制代码
		if (isConvert){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", name);

            jsonObject.put("minZ", positionZ);
            jsonObject.put("overMaxZ", overMinZ);
            jsonObject.put("overMinZ", overMaxZ);
            String jsonString = jsonObject.toString();

            System.out.println("擦除结果保存到模型数据集成功!!!");
            return jsonString;
        }else {
            System.out.println("擦除结果保存到模型数据集失败!!!!");
            return "擦除结果保存到模型数据集失败!!!!";
        }

三、前端调用后端接口

javascript 复制代码
			var sqlParameter = {
					"x": 116.0636726109858,
					"y": 30.032487387912454,
					"z": 600,
					"bottomRadius": 600,
					"height": 2000,
					"points": "[[116.03202241972726,30.028348734853576,1500],[116.04873386096398,30.01183763716355,2000],[116.09021417949586,30.033660215083376,1800],[116.07617627250876,30.058336989847938,1200]]"
				};
				var url = "http://localhost:8099/iServer/geoExtrudedBody";

				$.ajax({
					type: "post",
					url: url,
					data: sqlParameter,
					success: function (result) {
						var resultObj = JSON.parse(result);

						console.log(resultObj)
						//将超高部分绘制出来
						var s3mInstanceColc = new SuperMap3D.S3MInstanceCollection(scene._context);
						scene.primitives.add(s3mInstanceColc);
						s3mInstanceColc.add("http://localhost:8090/iserver/" + resultObj.name, {
							position: SuperMap3D.Cartesian3.fromDegrees(116.0636726109858, 30.032487387912454, resultObj.minZ),
							hpr: new SuperMap3D.HeadingPitchRoll(0, 0, 0),
							scale: new SuperMap3D.Cartesian3(1, 1, 1),
							color: SuperMap3D.Color.YELLOW
						});
					},
					error: function (msg) {
						console.log(msg);
					},
				})



相关推荐
s1mple“”2 小时前
基于电商场景的Java全栈面试实录:Spring Boot+微服务+AI技术深度解析
java·spring boot·微服务·高并发·分布式架构·电商系统·ai技术
Nakkhon2 小时前
软件工程实践——个人技术博客
java·开发语言
好奇的菜鸟2 小时前
Windows 环境下使用 Docker 部署 Java 开发中间件完全指南
java·windows·docker
代码or搬砖2 小时前
== 和 equals() 的区别
java·开发语言·jvm
koping_wu2 小时前
【leetcode】排序数组:快速排序、堆排序、归并排序
java·算法·leetcode
咘噜biu2 小时前
Java SpringBoot后端Filter包装请求(新增/覆盖请求头)
java·spring boot·filter·requestwrapper
历程里程碑2 小时前
LeetCode 283:原地移动零的优雅解法
java·c语言·开发语言·数据结构·c++·算法·leetcode
程序猿零零漆2 小时前
Spring之旅 - 记录学习 Spring 框架的过程和经验(五)Spring的后处理器BeanFactoryPostProcessor
java·学习·spring
虾说羊2 小时前
java中的反射详解
java·开发语言