標籤:worldwind 三維 eclipse 地理資訊
之前的一篇部落格是關於載入粗3D 模型的,見http://blog.csdn.net/giser_whu/article/details/43452703,這個地方還存在著不能載入紋理的問題,一直沒呢解決。那麼WW如何載入常用的3D 模型格式(3ds、obj、skp)呢,通過一番搜尋,瞭解到WW可以載入collada的dae格式的3D 模型,並且還可以載入kml\kmz檔案,那麼WW載入3D 模型的方法就出來了:首先將其他格式3D 模型轉換為kmz或kml檔案,再載入。這裡我是從su的3D 模型庫中下載的skp檔案,在su中可以直接轉換為kmz檔案,通過測試,這個方法是可行的。先來看下:
1.第一幅是德國標誌性建築——柏林奧林匹克體育場,可以看到效果還是可以的,不過沒有使用lod技術,一旦模型數量增多,會卡頓。
第二幅是也是德國地標性建築——柏林電視塔。
第三幅是3D City DB上的德國柏林一些collada3D 模型,需要的可以去下載做下測試
2.實現方法開頭已經明確了WW載入3D 模型的路線,WW又提供了載入kml/kmz檔案的demo(KMLViewer),所以要實現這個是很簡單的了,只需根據自己的需要改動原demo,整合到自己的工程下即可,這裡我改動原demo,編寫了SmartScopeKMLViewer,方法參見之前的部落格。所用到的資料,整理完上傳到CSDN資源,需要的可以去下載。:http://download.csdn.net/detail/liushuo_whu/85127393.原始碼
/*Copyright (C) 2001, 2010 United States Governmentas represented by the Administrator of theNational Aeronautics and Space Administration.All Rights Reserved. */package gov.nasa.worldwindx.examples.kml;import gov.nasa.worldwind.WorldWind;import gov.nasa.worldwind.avlist.AVKey;import gov.nasa.worldwind.awt.WorldWindowGLCanvas;import gov.nasa.worldwind.layers.RenderableLayer;import gov.nasa.worldwind.ogc.kml.KMLAbstractFeature;import gov.nasa.worldwind.ogc.kml.KMLRoot;import gov.nasa.worldwind.ogc.kml.impl.KMLController;import gov.nasa.worldwind.render.Offset;import gov.nasa.worldwind.retrieve.RetrievalService;import gov.nasa.worldwind.util.WWIO;import gov.nasa.worldwind.util.WWUtil;import gov.nasa.worldwind.util.layertree.KMLLayerTreeNode;import gov.nasa.worldwind.util.layertree.KMLNetworkLinkTreeNode;import gov.nasa.worldwind.util.layertree.LayerTree;import gov.nasa.worldwindx.examples.util.BalloonController;import gov.nasa.worldwindx.examples.util.HotSpotController;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.io.File;import java.io.IOException;import java.net.URL;import javax.swing.SwingUtilities;import javax.xml.stream.XMLStreamException;/** * 匯入KML或KMZ檔案,以圖層形式查看,KML或KMZ檔案的內容顯示為一個要素樹。在要素樹上點擊KML要素可以查看該要素 * ,在球上點擊要素可以彈出要素的描述資訊框 */public class SmartScopeKMLViewer{public static class KMLUtil{protected LayerTree layerTree; // 圖層樹protected RenderableLayer hiddenLayer; // 渲染圖層(圖層樹)protected HotSpotController hotSpotController; // 熱點controllerprotected KMLApplicationController kmlAppController; // KMLcontrollerprotected BalloonController balloonController; // BalloonControllerprotected WorldWindowGLCanvas wwd; // wwpublic KMLUtil(WorldWindowGLCanvas worldWindowGLCanvas){this.wwd = worldWindowGLCanvas;// 初始化圖層樹this.layerTree = new LayerTree(new Offset(20d, 160d, AVKey.PIXELS,AVKey.INSET_PIXELS));// this.layerTree.getModel().refresh(this.wwd.getModel().getLayers());// 圖層樹渲染圖層this.hiddenLayer = new RenderableLayer();this.hiddenLayer.addRenderable(this.layerTree);this.wwd.getModel().getLayers().add(this.hiddenLayer);// 註冊圖層選擇和氣球熱點選擇事件監聽this.hotSpotController = new HotSpotController(this.wwd);// 註冊kml事件監聽this.kmlAppController = new KMLApplicationController(this.wwd);this.balloonController = new BalloonController(this.wwd){@Overrideprotected void addDocumentLayer(KMLRoot document){addKMLLayer(document);}};// 關聯kml管理器和balloon管理器this.kmlAppController.setBalloonController(balloonController);// Set up to receive SSLHandshakeExceptions that occur during// resource retrieval.WorldWind.getRetrievalService().setSSLExceptionListener(new RetrievalService.SSLExceptionListener(){public void onException(Throwable e, String path){System.out.println(path);System.out.println(e);}});}/** * * @方法名稱: addKMLLayer ; * @方法描述: 添加KML圖層: ; * @參數 :@param kmlRoot * @傳回型別: void ; * @建立人:劉碩 ; * @建立時間:2015年3月17日 下午7:54:40; * @throws */protected void addKMLLayer(KMLRoot kmlRoot){// Create a KMLController to adapt the KMLRoot to the World WindKMLController kmlController = new KMLController(kmlRoot);// 添加kml圖層RenderableLayer layer = new RenderableLayer();layer.setName((String) kmlRoot.getField(AVKey.DISPLAY_NAME));layer.addRenderable(kmlController);this.wwd.getModel().getLayers().add(layer);// 添加kml圖層樹節點KMLLayerTreeNode layerNode = new KMLLayerTreeNode(layer, kmlRoot);this.layerTree.getModel().addLayer(layerNode);this.layerTree.makeVisible(layerNode.getPath());layerNode.expandOpenContainers(this.layerTree);// Listens to refresh property change events from KML network link// nodes. Upon receiving such an event this// expands any tree paths that represent open KML containers. When a// KML network link refreshes, its tree// node replaces its children with new nodes created from the// refreshed content, then sends a refresh// property change event through the layer tree. By expanding open// containers after a network link refresh,// we ensure that the network link tree view appearance is// consistent with the KML specification.layerNode.addPropertyChangeListener(AVKey.RETRIEVAL_STATE_SUCCESSFUL,new PropertyChangeListener(){public void propertyChange(final PropertyChangeEvent event){if (event.getSource() instanceof KMLNetworkLinkTreeNode){// Manipulate the tree on the EDT.SwingUtilities.invokeLater(new Runnable(){public void run(){((KMLNetworkLinkTreeNode) event.getSource()).expandOpenContainers(layerTree);wwd.redraw();}});}}});}}/** * * @項目名稱:worldwind-1.5.0 * @類名稱:WorkerThread * @類描述:載入KML檔案線程類 * @建立人:劉碩 * @建立時間:2015年3月17日 下午7:58:38 * @修改備忘: * @版本: */public static class WorkerThread extends Thread{/** * 待載入kml檔案,在建構函式中初始化 */protected Object kmlSource;/** * kmlapp */protected KMLUtil KMLUtil;public WorkerThread(Object kmlSource, KMLUtil KMLUtil){this.kmlSource = kmlSource;this.KMLUtil = KMLUtil;}/** * Loads this worker thread's KML source into a new * <code>{@link gov.nasa.worldwind.ogc.kml.KMLRoot}</code>, then adds * the new <code>KMLRoot</code> to this worker thread's * <code>AppFrame</code>. The <code>KMLRoot</code>'s * <code>AVKey.DISPLAY_NAME</code> field contains a display name created * from either the KML source or the KML root feature name. * <p/> * If loading the KML source fails, this prints the exception and its * stack trace to the standard error stream, but otherwise does nothing. */public void run(){try{KMLRoot kmlRoot = this.parse();// 設定文檔的顯示名稱kmlRoot.setField(AVKey.DISPLAY_NAME,formName(this.kmlSource, kmlRoot));// 啟動一個任務進程載入解析的kml檔案final KMLRoot finalKMLRoot = kmlRoot;SwingUtilities.invokeLater(new Runnable(){public void run(){KMLUtil.addKMLLayer(finalKMLRoot);}});}catch (Exception e){e.printStackTrace();}}/** * * @方法名稱: parse ; * @方法描述: 解析KML文檔 ; * @參數 :@return 返回KMLRoot * @參數 :@throws IOException:文檔不可讀 * @參數 :@throws XMLStreamException :文檔解析出現錯誤 * @傳回型別: KMLRoot ; * @建立人:劉碩 ; * @建立時間:2015年3月17日 下午8:02:59; * @throws */protected KMLRoot parse() throws IOException, XMLStreamException{// KMLRoot.createAndParse will attempt to parse the document using a// namespace aware parser, but if that// fails due to a parsing error it will try again using a namespace// unaware parser. Note that this second// step may require the document to be read from the network again// if the kmlSource is a stream.return KMLRoot.createAndParse(this.kmlSource);}}protected static String formName(Object kmlSource, KMLRoot kmlRoot){KMLAbstractFeature rootFeature = kmlRoot.getFeature();if (rootFeature != null && !WWUtil.isEmpty(rootFeature.getName()))return rootFeature.getName();if (kmlSource instanceof File)return ((File) kmlSource).getName();if (kmlSource instanceof URL)return ((URL) kmlSource).getPath();if (kmlSource instanceof String&& WWIO.makeURL((String) kmlSource) != null)return WWIO.makeURL((String) kmlSource).getPath();return "KML Layer";}}
World Wind Java開發之十五——載入3D 模型