WorldWind Java版加载shp文件,并实现三维效果

之前介绍了在WorldWind Java版中加载WMS服务图层,想学习的小伙伴,可以翻看上一篇文章。WorldWind是实现了三维效果的展示,当然少不了加载三维模型,我翻看WorldWind的源码,发现WorldWind支持加载KMZ格式的三维模型。这就比较精细了。如果有需要加载KMZ格式模型的需求,可以在下方留言,后续发加载KMZ格式的代码发出来。今天就记录下加载shape文件,实现三维效果。由于模型所致,就比较粗糙。
首先看一下加载后的效果:
在这里插入图片描述

1.shape文件

这里的shape文件是带有高度的矢量文件,可以使用ArcMap制作。如下图:
在这里插入图片描述
如图这个是一个机场的shape文件。这个文件属性表中有一列表明了每个像素的高度。如下图。
在这里插入图片描述
可以看到属性表中包含许多信息,这里只需看“hhh”列表即可,这里表示每个像素的高程。这个值就是形成三维效果的关键。准备好这个文件后就可以开始编码之路。

2.编写代码

直接贴代码:

/*
* 加载带有高度的shape文件,并将高度进行拉伸,形成三维效果
* 2021年11月24日14:14:17
* */
public class ModelLayer {
    private static RenderableLayer layer;                  //三维模型的渲染图层

    //加载三维模型的方法
    public static void init3DModel(WorldWindowGLCanvas wwd, String filePath){
        Shapefile shapefile = new Shapefile(filePath);
        layer = new RenderableLayer();
        layer.setName("model");                           //图层命名为“model”,这个可以自定义
        layer.setPickEnabled(true);

        try {
            while (shapefile.hasNext()) {
                ShapefileRecord record = shapefile.nextRecord();
                layer.addRenderable(makeShape(record));
            }
            wwd.getModel().getLayers().add(layer);
        } finally {
            shapefile.close();
        }
    }

    private static ExtrudedPolygon makeShape(ShapefileRecord record) {
        String IMAGE_PATH = "images/ic_wall.jpg";          //这个是贴图纹理的路径
        Double height = null;                              //每个像素的高度值

        /*
         * 这里需要注意一下,获取到的高度值必须大于0,当有小于等于0的高度值时,
         * 需要将高度值设为0.1即可。且所有值不能忽略,否则会报错
         * */
        Object o = record.getAttributes().getValue("hhh"); //hhh为shape文件中表示高度的字段值。也就是在第一步中提到的表示高程的字段。                                                  
        if (o != null) {
            Double h = Double.parseDouble(o.toString());
            if (h<=0){                                     //如果有小于等于0的值,设为0.1,只要大于0即可。
                h=0.1;
            }
            height=h*20;                                   //将高度值拉高20倍,否则原始的高度值,三维效果不明显
        }

        // 顶部属性
        ShapeAttributes capAttrs = new BasicShapeAttributes();
        capAttrs.setOutlineMaterial(Material.GRAY);
        capAttrs.setInteriorMaterial(Material.LIGHT_GRAY);

        // 边属性
        ShapeAttributes sideAttributes = new BasicShapeAttributes();
        sideAttributes.setInteriorMaterial(Material.LIGHT_GRAY);
        sideAttributes.setOutlineMaterial(Material.DARK_GRAY);
        sideAttributes.setImageSource(IMAGE_PATH);

        // 创建拉伸多边形
        VecBuffer vb = record.getPointBuffer(0);
        gov.nasa.worldwind.render.airspaces.Polygon pgonAirspace = new Polygon(vb.getLocations());                                     //根据点串构建多边形

        //纹理
        ArrayList<String> textures = new ArrayList<String>();
        for (int i = 0; i < pgonAirspace.getLocations().size()-1; i++) {
            textures.add(IMAGE_PATH);
        }

        //给多边形添加上高度和纹理。
        ExtrudedPolygon polygon = new ExtrudedPolygon(pgonAirspace.getLocations(), height, textures);                 //有纹理
        //ExtrudedPolygon polygon = new ExtrudedPolygon(pgonAirspace.getLocations(), height, null);                       //纹理设为null,即可设为无纹理。

        polygon.setCapAttributes(capAttrs);
        polygon.setSideAttributes(sideAttributes);
        polygon.setAltitudeMode(WorldWind.CLAMP_TO_GROUND);
        return polygon;
    }

    /*
    * 移除指定名字的三维模型
    * */
    public static void removeModel(WorldWindowGLCanvas wwd,String name){
        if (wwd.getModel().getLayers().getLayerByName(name)!=null){
            wwd.getModel().getLayers().remove(wwd.getModel().getLayers().getLayerByName(name));
            wwd.redrawNow();
        }
    }
}

代码就是这些,是不是很简单。使用的时候,直接调用即可。参数有两个,一个是三维球,一个是shape文件的路径。

猜你喜欢

转载自blog.csdn.net/nanjumufeng/article/details/121513804