一、KML图标更换
在WorldWind中,KML文件的PointPlacemark默认标记的ImageAddress以及Scale属性,我不大喜欢这种样式。类似于下图:
所以下面我对该图标的样式进行更改。
1、打开源代码中src->gov.nasa.worldwind.ogc.kml.impl包中的KMLPointPlacemarkImpl文件,剖析文件:
1)构造方法的主要目的是初始化参数,置于一遍。先分析render()方法,明显地,方法主要为一个判断语句(判断是否被突出显示)。同样的,PointPlacemarkAttributes属性都被makeAttributesCurrent()方法控制。
2)F3进入makeAttributesCurrent(),可设置3种样式LineStyle、IconStyle、LabelStyle,我们分析IconStyle,通过this.assemblePointAttributes(attrs, (KMLIconStyle) subStyle);
可以知道Icon属性变化通过assemblePointAttributes()方法控制。
3)F3进入assemblePointAttributes(),便可以更改ImageAddress、Scale更改。把
try
{
localAddress = this.parent.getRoot().getSupportFilePath(href);
}
catch (IOException e)
{
String message = Logging.getMessage("generic.UnableToResolveReference", href);
Logging.logger().warning(message);
}
代码注释掉,并编写如下代码
if(this.isHighlighted()){
localAddress="E:/ESI/WorkSpace/WorldWindJava/testData/images/pushpins/plain-red.png";
attrs.setScale(0.5);
}else{
localAddress="E:/ESI/WorkSpace/WorldWindJava/testData/images/pushpins/plain-blue.png";
attrs.setScale(0.4);
}
在这需要注意两个问题。一是localAddress的值,最初我用的相对定位“images/pushpins/plain-blue.png”,在WorldWindJava源码中进行测试,可以正常显示。可是我把WorldWindJava打包配置到WWJMFS项目中,会出现问题,建议改成绝对路径。二是在调用setScale()方法后,需要把后面的
if (style.getScale() != null)
attrs.setScale(style.getScale());
代码注释掉,不然不能正常显示。
源码改成这样即可,然后对WorldWindJava打包配置到WWJMFS项目路径中。
2、在WWJMFS项目中,新建KMLViewerUtil.java文件,代码如下:
package esi.control;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.event.SelectEvent;
import gov.nasa.worldwind.retrieve.RetrievalService;
import gov.nasa.worldwindx.examples.kml.KMLApplicationController;
import gov.nasa.worldwindx.examples.util.*;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.ogc.kml.*;
import gov.nasa.worldwind.ogc.kml.impl.KMLController;
import gov.nasa.worldwind.util.*;
import javax.swing.*;
import javax.xml.stream.XMLStreamException;
import java.io.*;
import java.net.URL;
public class KMLViewerUtil {
public static class WorkerThread extends Thread
{
protected Object kmlSource;
protected WorldWindow wwd;
protected HotSpotController hotSpotController;
protected HighlightController highlightController;
protected KMLApplicationController kmlAppController;
protected BalloonController balloonController;
public WorkerThread(Object kmlSource,WorldWindow wwd)
{
this.kmlSource = kmlSource;
this.wwd=wwd;
}
public void run()
{
try
{
//加载监听器
// Add a controller to handle input events on the layer selector and on browser balloons.
this.hotSpotController = new HotSpotController(this.wwd);
// Add a contriller to handle Icons` change by judge whether the PointPlacemark highlighted or not.
this.highlightController = new HighlightController(this.wwd, SelectEvent.ROLLOVER);
// Add a controller to handle common KML application events.
this.kmlAppController = new KMLApplicationController(this.wwd);
// Add a controller to display balloons when placemarks are clicked. We override the method addDocumentLayer
// so that loading a KML document by clicking a KML balloon link displays an entry in the on-screen layer
// tree.
this.balloonController = new BalloonController(this.wwd)
{
@Override
protected void addDocumentLayer(KMLRoot document)
{
addKMLLayer(document,wwd);
}
};
// Give the KML app controller a reference to the BalloonController so that the app controller can open
// KML feature balloons when feature's are selected in the on-screen layer tree.
this.kmlAppController.setBalloonController(balloonController);
//
KMLRoot kmlRoot = this.parse();
// Set the document's display name
kmlRoot.setField(AVKey.DISPLAY_NAME, formName(this.kmlSource, kmlRoot));
// Schedule a task on the EDT to add the parsed document to a layer
final KMLRoot finalKMLRoot = kmlRoot;
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
addKMLLayer(finalKMLRoot,wwd);
}
});
// 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);
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
protected void addKMLLayer(KMLRoot kmlRoot,WorldWindow wwd)
{
// Create a KMLController to adapt the KMLRoot to the World Wind renderable interface.
KMLController kmlController = new KMLController(kmlRoot);
// Adds a new layer containing the KMLRoot to the end of the WorldWindow's layer list. This
// retrieves the layer name from the KMLRoot's DISPLAY_NAME field.
RenderableLayer layer = new RenderableLayer();
layer.setName((String) kmlRoot.getField(AVKey.DISPLAY_NAME));
layer.addRenderable(kmlController);
layer.setEnabled(true);
this.wwd.getModel().getLayers().add(layer);
}
/**
* Parse the KML document.
*
* @return The parsed document.
*
* @throws IOException if the document cannot be read.
* @throws XMLStreamException if document cannot be parsed.
*/
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";
}
}
在WWJMFS.java文件中通过new KMLViewerUtil.WorkerThread(new File("E:/ESI/WorkSpace/WWJMFS/testData/Islands/islands.kml"), wwd).start();
进行调用。即可完成kml文件图标的更换。效果如图
注:kml文件显示乱码问题,在src->gov.nasa.worldwind.render包中PointPlacemarkAttributes.java文件,更改为
public static final Font DEFAULT_LABEL_FONT = Font.decode("宋体-BOLD-14");
即可。
二、指南针图标更换
只需更改src->gov.nasa.worldwind.layers中CompassLayer.java文件,
protected String iconFilePath = "images/compass.png";
本章结束