• World Wind Java开发之八——加载本地缓存文件构建大范围三维场景(


    http://blog.csdn.net/giser_whu/article/details/42044599

    上一篇博客主要是针对小文件直接导入WW中显示,然而当文件特别大时,这种方式就不太可行。因此要将大文件切片,生成本地缓存,WW可以加载本地缓存文件,保障浏览场景时的流畅性。

    1、使用Global Mapper生成WW缓存切片

    使用Global Mapper生成WW缓存切片的步骤已上传至使用GlobalMapper生成WW缓存切片,这里不再赘述。生成后的切片可以放在任意文件夹下,目前参考了WWJ自带的例子InstallImageryAndElevationsDemo,暂时将数据放在C:ProgramDataWorldWindInstalled目录下,如下图所示。
    生成的XML文件修改如下:

    2、参照InstallImageryAndElevationsDemo示例实现缓存文件的初始化加载

    未多做修改,写了一个加载缓存数据的类LoadCacheData,代码如下所示。
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /** 
    2.  * @Copyright 2014-2020 @奔跑的鸡丝 
    3.  **/  
    4.   
    5. package edu.whu.vge.util;  
    6.   
    7. import edu.whu.vge.util.JavaCheckBoxTree.CheckBoxTreeNode;  
    8. import gov.nasa.worldwind.Factory;  
    9. import gov.nasa.worldwind.WorldWind;  
    10. import gov.nasa.worldwind.avlist.AVKey;  
    11. import gov.nasa.worldwind.avlist.AVList;  
    12. import gov.nasa.worldwind.avlist.AVListImpl;  
    13. import gov.nasa.worldwind.awt.WorldWindowGLCanvas;  
    14. import gov.nasa.worldwind.cache.FileStore;  
    15. import gov.nasa.worldwind.exception.WWRuntimeException;  
    16. import gov.nasa.worldwind.geom.Sector;  
    17. import gov.nasa.worldwind.globes.Earth;  
    18. import gov.nasa.worldwind.globes.ElevationModel;  
    19. import gov.nasa.worldwind.layers.Layer;  
    20. import gov.nasa.worldwind.terrain.CompoundElevationModel;  
    21. import gov.nasa.worldwind.util.DataConfigurationFilter;  
    22. import gov.nasa.worldwind.util.DataConfigurationUtils;  
    23. import gov.nasa.worldwind.util.Logging;  
    24. import gov.nasa.worldwind.util.WWIO;  
    25. import gov.nasa.worldwind.util.WWXML;  
    26.   
    27. import java.awt.Component;  
    28. import java.io.File;  
    29.   
    30. import javax.swing.JTree;  
    31. import javax.swing.SwingUtilities;  
    32. import javax.swing.tree.DefaultMutableTreeNode;  
    33. import javax.xml.xpath.XPath;  
    34.   
    35. import org.w3c.dom.Document;  
    36. import org.w3c.dom.Element;  
    37.   
    38. /** 
    39.  * @项目名称:GF_ZHJCYPG 
    40.  * @类名称:LoadCacheData 
    41.  * @类描述: 加载缓存数据 
    42.  * @创建人:奔跑的鸡丝 
    43.  * @创建时间:2014-12-19 下午4:30:49 
    44.  * @修改备注: 
    45.  * @版本: 
    46.  */  
    47.   
    48. public class LoadCacheData  
    49. {  
    50.     private static WorldWindowGLCanvas worldWindowGLCanvas;  
    51.     private static JTree layerJTree;  
    52.   
    53.     /** 
    54.      *  
    55.      * 创建一个新的实例 LoadCacheData. 
    56.      *  
    57.      * @param worWindowGLCanvas 
    58.      */  
    59.     public LoadCacheData(WorldWindowGLCanvas worWindowGLCanvas, JTree jTree)  
    60.     {  
    61.         LoadCacheData.setWorldWindowGLCanvas(worWindowGLCanvas);  
    62.         LoadCacheData.setLayerJTree(jTree);  
    63.     }  
    64.   
    65.     /** 
    66.      *  
    67.      * @方法名称: loadPreviouslyInstalledData ; 
    68.      * @方法描述: 加载已有的缓存文件 ; 
    69.      * @参数 : 
    70.      * @返回类型: void ; 
    71.      * @创建人:奔跑的鸡丝 ; 
    72.      * @创建时间:2014-12-19 下午7:06:09; 
    73.      * @throws 
    74.      */  
    75.     public void loadPreviouslyInstalledData()  
    76.     {  
    77.   
    78.         Thread thread = new Thread(new Runnable()  
    79.         {  
    80.   
    81.             @Override  
    82.             public void run()  
    83.             {  
    84.                 // TODO Auto-generated method stub  
    85.                 loadInstalledDataFromFileStore(WorldWind.getDataFileStore());  
    86.             }  
    87.         });  
    88.         thread.start();  
    89.     }  
    90.   
    91.     /** 
    92.      *  
    93.      * @方法名称: loadInstalledDataFromFileStore ; 
    94.      * @方法描述: TODO ; 
    95.      * @参数 :@param fileStore 
    96.      * @返回类型: void ; 
    97.      * @创建人:奔跑的鸡丝 ; 
    98.      * @创建时间:2014-12-19 下午7:06:42; 
    99.      * @throws 
    100.      */  
    101.     protected void loadInstalledDataFromFileStore(FileStore fileStore)  
    102.     {  
    103.         // 便利已有的缓存文件  
    104.         for (File file : fileStore.getLocations())  
    105.         {  
    106.             // 文件存在并且是缓存文件目录  
    107.             if (file.exists() && fileStore.isInstallLocation(file.getPath()))  
    108.             {  
    109.                 System.out.println(file.getPath());  
    110.                 loadInstalledDataFromDirectory(file);  
    111.             }  
    112.   
    113.         }  
    114.     }  
    115.   
    116.     /** 
    117.      *  
    118.      * @方法名称: loadInstalledDataFromDirectory ; 
    119.      * @方法描述: 从文件目录加载缓存数据 ; 
    120.      * @参数 :@param dir 
    121.      * @返回类型: void ; 
    122.      * @创建人:奔跑的鸡丝 ; 
    123.      * @创建时间:2014-12-19 下午7:43:36; 
    124.      * @throws 
    125.      */  
    126.     private void loadInstalledDataFromDirectory(File dir)  
    127.     {  
    128.         /** 
    129.          * 获取缓存文件xml配置文件的在缓存文件目录的相对目录,如LandsatLandsat.xml 
    130.          */  
    131.         String[] names = WWIO.listDescendantFilenames(dir,  
    132.                 new DataConfigurationFilter(), false);  
    133.         if (names == null || names.length == 0)  
    134.             return;  
    135.   
    136.         for (String filename : names)  
    137.         {  
    138.             Document doc = null;  
    139.   
    140.             try  
    141.             {  
    142.                 // 根据缓存文件XML描述文件创建Document对象  
    143.                 File dataConfigFile = new File(dir, filename);  
    144.                 doc = WWXML.openDocument(dataConfigFile);  
    145.                 doc = DataConfigurationUtils.convertToStandardDataConfigDocument(doc);  
    146.             }  
    147.             catch (WWRuntimeException e)  
    148.             {  
    149.                 e.printStackTrace();  
    150.             }  
    151.   
    152.             if (doc == null)  
    153.                 continue;  
    154.   
    155.             // 由于数据配置文件来自于已有的文件,因此不能保证它是由当前版本WW's Installer  
    156.             // 产生的。可能是由之前版本或其他应用程序产生的,因此要为可能缺失的参数设置备用值(这些参数需要用来构建图层或高程模拟)  
    157.             AVList params = new AVListImpl();  
    158.             setFallbackParams(doc, filename, params);  
    159.             // 添加数据  
    160.             addInstalledData(doc, params);  
    161.         }  
    162.     }  
    163.   
    164.     /** 
    165.      *  
    166.      * @方法名称: setFallbackParams ; 
    167.      * @方法描述: 设置备用参数值 ; 
    168.      * @参数 :@param dataConfig :数据配置XML文件 
    169.      * @参数 :@param filename :文件名 
    170.      * @参数 :@param params :参数列表 
    171.      * @返回类型: void ; 
    172.      * @创建人:奔跑的鸡丝 ; 
    173.      * @创建时间:2014-12-20 下午12:21:03; 
    174.      * @throws 
    175.      */  
    176.     private void setFallbackParams(Document dataConfig, String filename,  
    177.             AVList params)  
    178.     {  
    179.         XPath xpath = WWXML.makeXPath();  
    180.         Element domElement = dataConfig.getDocumentElement();  
    181.   
    182.         // If the data configuration document doesn't define a cache name, then  
    183.         // compute one using the file's path  
    184.         // relative to its file cache directory.  
    185.         String s = WWXML.getText(domElement, "DataCacheName", xpath);  
    186.         if (s == null || s.length() == 0)  
    187.             DataConfigurationUtils.getDataConfigCacheName(filename, params);  
    188.   
    189.         // If the data configuration document doesn't define the data's extreme  
    190.         // elevations, provide default values using  
    191.         // the minimum and maximum elevations of Earth.  
    192.         String type = DataConfigurationUtils.getDataConfigType(domElement);  
    193.         if (type.equalsIgnoreCase("ElevationModel"))  
    194.         {  
    195.             if (WWXML.getDouble(domElement, "ExtremeElevations/@min", xpath) == null)  
    196.                 params.setValue(AVKey.ELEVATION_MIN, Earth.ELEVATION_MIN);  
    197.             if (WWXML.getDouble(domElement, "ExtremeElevations/@max", xpath) == null)  
    198.                 params.setValue(AVKey.ELEVATION_MAX, Earth.ELEVATION_MAX);  
    199.         }  
    200.     }  
    201.   
    202.     /** 
    203.      *  
    204.      * @方法名称: addInstalledData ; 
    205.      * @方法描述: 添加缓存数据 ; 
    206.      * @参数 :@param dataConfig 
    207.      * @参数 :@param params 
    208.      * @返回类型: void ; 
    209.      * @创建人:奔跑的鸡丝 ; 
    210.      * @创建时间:2014-12-20 下午12:22:29; 
    211.      * @throws 
    212.      */  
    213.     private void addInstalledData(final Document dataConfig, final AVList params)  
    214.     {  
    215.         if (!SwingUtilities.isEventDispatchThread())  
    216.         {  
    217.             SwingUtilities.invokeLater(new Runnable()  
    218.             {  
    219.                 public void run()  
    220.                 {  
    221.                     addInstalledData(dataConfig, params);  
    222.                 }  
    223.             });  
    224.         }  
    225.         else  
    226.         {  
    227.             addInstalledCacheData(dataConfig.getDocumentElement(), params);  
    228.         }  
    229.   
    230.     }  
    231.   
    232.     /** 
    233.      *  
    234.      * @方法名称: addInstalledCacheData ; 
    235.      * @方法描述: 添加已有缓存数据 ; 
    236.      * @参数 :@param domElement :数据XML描述文件 
    237.      * @参数 :@param params :参数列表 
    238.      * @返回类型: void ; 
    239.      * @创建人:奔跑的鸡丝 ; 
    240.      * @创建时间:2014-12-19 下午8:02:21; 
    241.      * @throws 
    242.      */  
    243.     public void addInstalledCacheData(final Element domElement,  
    244.             final AVList params)  
    245.     {  
    246.         if (domElement == null)  
    247.         {  
    248.             String message = Logging.getMessage("nullValue.DocumentIsNull");  
    249.             Logging.logger().severe(message);  
    250.             throw new IllegalArgumentException(message);  
    251.         }  
    252.   
    253.         String description = getDescription(domElement); // 图层名称  
    254.         Sector sector = getSector(domElement); // 图层范围  
    255.         System.out.println(description);  
    256.         System.out.println(sector);  
    257.         addToWorldWindow(domElement, params);  
    258.   
    259.     }  
    260.   
    261.     /** 
    262.      *  
    263.      * @方法名称: addToWorldWindow ; 
    264.      * @方法描述: 将缓存文件加入WW ; 
    265.      * @参数 :@param domElement 
    266.      * @参数 :@param params 
    267.      * @返回类型: void ; 
    268.      * @创建人:奔跑的鸡丝 ; 
    269.      * @创建时间:2014-12-19 下午4:44:08; 
    270.      * @throws 
    271.      */  
    272.     private void addToWorldWindow(Element domElement, AVList params)  
    273.     {  
    274.         String type = DataConfigurationUtils.getDataConfigType(domElement);  
    275.         if (type == null)  
    276.             return;  
    277.   
    278.         if (type.equalsIgnoreCase("Layer"))  
    279.         {  
    280.             addLayerToWorldWindow(domElement, params);  
    281.         }  
    282.         else if (type.equalsIgnoreCase("ElevationModel"))  
    283.         {  
    284.             addElevationModelToWorldWindow(domElement, params);  
    285.         }  
    286.     }  
    287.   
    288.     /** 
    289.      *  
    290.      * @方法名称: addLayerToWorldWindow ; 
    291.      * @方法描述: 向WW中添加图层 ; 
    292.      * @参数 :@param domElement 
    293.      * @参数 :@param params 
    294.      * @返回类型: void ; 
    295.      * @创建人:奔跑的鸡丝 ; 
    296.      * @创建时间:2014-12-19 下午4:45:06; 
    297.      * @throws 
    298.      */  
    299.     private void addLayerToWorldWindow(Element domElement, AVList params)  
    300.     {  
    301.         Layer layer = null;  
    302.         try  
    303.         {  
    304.             // Factory创建的图层默认是不可见的  
    305.             Factory factory = (Factory) WorldWind.createConfigurationComponent(AVKey.LAYER_FACTORY);  
    306.             layer = (Layer) factory.createFromConfigSource(domElement, params);  
    307.         }  
    308.         catch (Exception e)  
    309.         {  
    310.             String message = Logging.getMessage(  
    311.                     "generic.CreationFromConfigurationFailed",  
    312.                     DataConfigurationUtils.getDataConfigDisplayName(domElement));  
    313.             Logging.logger().log(java.util.logging.Level.SEVERE, message, e);  
    314.         }  
    315.   
    316.         if (layer == null)  
    317.             return;  
    318.         layer.setEnabled(true); // 设置图层可见  
    319.   
    320.         // 添加至WW  
    321.         if (!getWorldWindowGLCanvas().getModel().getLayers().contains(layer))  
    322.         {  
    323.             getWorldWindowGLCanvas().getModel().getLayers().add(layer);  
    324.             // System.out.println(pLayerTree.getModel().getRoot().toString());  
    325.             Object rootObject = layerJTree.getModel().getRoot();  
    326.             if (!layerJTree.getModel().isLeaf(rootObject))  
    327.             {  
    328.                 int count = layerJTree.getModel().getChildCount(rootObject);  
    329.                 for (int i = 0; i < count; i++)  
    330.                 {  
    331.                     String childNodeNameString = layerJTree.getModel().getChild(  
    332.                             rootObject, i).toString();  
    333.                     if (childNodeNameString.equals("影像图层"))  
    334.                     {  
    335.                         ((DefaultMutableTreeNode) layerJTree.getModel().getChild(  
    336.                                 rootObject, i)).add(new CheckBoxTreeNode(  
    337.                                 layer.getName()));  
    338.                         layerJTree.updateUI();  
    339.                     }  
    340.                 }  
    341.             }  
    342.   
    343.         }  
    344.     }  
    345.   
    346.     /** 
    347.      *  
    348.      * @方法名称: addElevationModelToWorldWindow ; 
    349.      * @方法描述: 添加高程图层 ; 
    350.      * @参数 :@param domElement 
    351.      * @参数 :@param params 
    352.      * @返回类型: void ; 
    353.      * @创建人:奔跑的鸡丝 ; 
    354.      * @创建时间:2014-12-19 下午4:51:37; 
    355.      * @throws 
    356.      */  
    357.     private void addElevationModelToWorldWindow(Element domElement,  
    358.             AVList params)  
    359.     {  
    360.         ElevationModel em = null;  
    361.         try  
    362.         {  
    363.             Factory factory = (Factory) WorldWind.createConfigurationComponent(AVKey.ELEVATION_MODEL_FACTORY);  
    364.             em = (ElevationModel) factory.createFromConfigSource(domElement,  
    365.                     params);  
    366.         }  
    367.         catch (Exception e)  
    368.         {  
    369.             String message = Logging.getMessage(  
    370.                     "generic.CreationFromConfigurationFailed",  
    371.                     DataConfigurationUtils.getDataConfigDisplayName(domElement));  
    372.             Logging.logger().log(java.util.logging.Level.SEVERE, message, e);  
    373.         }  
    374.   
    375.         if (em == null)  
    376.             return;  
    377.   
    378.         ElevationModel defaultElevationModel = getWorldWindowGLCanvas().getModel().getGlobe().getElevationModel();  
    379.         if (defaultElevationModel instanceof CompoundElevationModel)  
    380.         {  
    381.             if (!((CompoundElevationModel) defaultElevationModel).containsElevationModel(em))  
    382.                 ((CompoundElevationModel) defaultElevationModel).addElevationModel(em);  
    383.         }  
    384.         else  
    385.         {  
    386.             CompoundElevationModel cm = new CompoundElevationModel();  
    387.             cm.addElevationModel(defaultElevationModel);  
    388.             cm.addElevationModel(em);  
    389.             getWorldWindowGLCanvas().getModel().getGlobe().setElevationModel(cm);  
    390.         }  
    391.     }  
    392.   
    393.     /** 
    394.      * 获取缓存文件类型 获取缓存配置文件描述:是Layer或者是Elevation 
    395.      *  
    396.      * @方法名称: getDescription ; 
    397.      * @方法描述: TODO ; 
    398.      * @参数 :@param domElement 
    399.      * @参数 :@return 
    400.      * @返回类型: String ; 
    401.      * @创建人:奔跑的鸡丝 ; 
    402.      * @创建时间:2014-12-19 下午4:53:26; 
    403.      * @throws 
    404.      */  
    405.     private String getDescription(Element domElement)  
    406.     {  
    407.         String displayName = DataConfigurationUtils.getDataConfigDisplayName(domElement);  
    408.         String type = DataConfigurationUtils.getDataConfigType(domElement);  
    409.   
    410.         StringBuilder sb = new StringBuilder(displayName);  
    411.   
    412.         if (type.equalsIgnoreCase("Layer"))  
    413.         {  
    414.             sb.append(" (Layer)");  
    415.         }  
    416.         else if (type.equalsIgnoreCase("ElevationModel"))  
    417.         {  
    418.             sb.append(" (Elevations)");  
    419.         }  
    420.   
    421.         return sb.toString();  
    422.     }  
    423.   
    424.     /** 
    425.      * 获取图层范围 
    426.      *  
    427.      * @方法名称: getSector ; 
    428.      * @方法描述: TODO ; 
    429.      * @参数 :@param domElement 
    430.      * @参数 :@return 
    431.      * @返回类型: Sector ; 
    432.      * @创建人:奔跑的鸡丝 ; 
    433.      * @创建时间:2014-12-19 下午4:54:17; 
    434.      * @throws 
    435.      */  
    436.     protected static Sector getSector(Element domElement)  
    437.     {  
    438.         return WWXML.getSector(domElement, "Sector", null);  
    439.     }  
    440.   
    441.     public static WorldWindowGLCanvas getWorldWindowGLCanvas()  
    442.     {  
    443.         return worldWindowGLCanvas;  
    444.     }  
    445.   
    446.     public static void setWorldWindowGLCanvas(  
    447.             WorldWindowGLCanvas worldWindowGLCanvas)  
    448.     {  
    449.         LoadCacheData.worldWindowGLCanvas = worldWindowGLCanvas;  
    450.     }  
    451.   
    452.     public JTree getLayerJTree()  
    453.     {  
    454.         return layerJTree;  
    455.     }  
    456.   
    457.     public static void setLayerJTree(JTree layerJTree)  
    458.     {  
    459.         LoadCacheData.layerJTree = layerJTree;  
    460.     }  
    461.   
    462. }  

    3、高程数据的加载

    高程数据采用NASA的30m公开DEM数据,使用World Wind Server发布即可,详见前面的搭建本地World wind Severe服务器。最终实现效果图如下图所示。
    PS:年末各种忙啊,项目总算结题,明天小组年会,预祝一切顺利!欢迎大家留言交流,共享自己的学习笔记。
    World Wind Java的资料实在太少啦,断断续续总算搭建起了三维框架,后面陆续添加功能,计划做一个基于新安江模型的洪涝模拟仿真模块,将之前做的洪涝模拟和参数率定、径流模拟全部整合到自己的这个平台上来。
    ---------------------------------分割线(2015年1月13日)-----------------------------------
    补充:关于LoadCacheData的使用,只需在程序初始化时加入以下两句代码即可:
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. // 加载缓存数据  
    2.             LoadCacheData loadCacheData = new LoadCacheData(wGlCanvas,  
    3.                     layerJTree);  
    4.             loadCacheData.loadPreviouslyInstalledData();  
    其中layerJTree是图层树,大家可以不要这个参数,修改相应代码即可,另外如何测试自己的切片数据是否加载成功,可以参考示例中的InstallImageryAndElevationsDemo这个。可能有些朋友不知如何运行自带的示例,下面我贴图说明下哈(假设已添加Worldwind.jar文件,并且已使用GlobalMapper切片放置C:ProgramDataWorldWindInstalled文件夹下)
    如果结果如上图所示,说明数据已加载成功。如果还未成功,检查缓存数据xml配置文件是否正确,可以跟一下源代码看下是如何加载缓存数据的。
    PS:另外,最近期末考试,再加上其他项目的事情,更新有些慢哈。后面会陆续更新,欢迎大家留言交流!
  • 相关阅读:
    java程序后台报错java.net.SocketException: Too many open files
    linux中,查看某个命令是来自哪个RPM包或者是通过哪个RPM包安装的
    Oracle卸载之linux快速卸载rac脚本-一键卸载
    40个DBA日常维护的SQL脚本
    Oracle SQL开发 之 Select语句完整的执行顺序
    Oracle开发 之 主-外键约束FK及约束的修改
    drop user 报错ora-00604
    oracle Bug 4287115(ora-12083)
    Ora-1157 ora-1110错误解决案例一枚
    rac库grid目录权限(6751)导致数据库宕机案例 此方法仅用于紧急救助
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6774645.html
Copyright © 2020-2023  润新知