/** * Resolves a reference to a local or remote file or element. If the link refers to an element in * the current document, this method returns that element. If the link refers to a remote * document, this method will initiate asynchronous retrieval of the document, and return a URL of * the downloaded document in the file cache, if it is available locally. If the link identifies a * COLLADA document, the document will be returned as a parsed ColladaRoot. * * @param link the address of the document or element to resolve. This may be a full URL, a URL * fragment that identifies an element in the current document ("#myElement"), or a URL and a * fragment identifier ("http://server.com/model.dae#myElement"). * @return the requested element, or null if the element is not found. * @throws IllegalArgumentException if the address is null. */ public Object resolveReference(String link) { if (link == null) { String message = Logging.getMessage("nullValue.DocumentSourceIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } try { String[] linkParts = link.split("#"); String linkBase = linkParts[0]; String linkRef = linkParts.length > 1 ? linkParts[1] : null; // See if it's a reference to an internal element. if (WWUtil.isEmpty(linkBase) && !WWUtil.isEmpty(linkRef)) return this.getItemByID(linkRef); // Interpret the path relative to the current document. String path = this.getSupportFilePath(linkBase); if (path == null) path = linkBase; // See if it's an already found and parsed COLLADA file. Object o = WorldWind.getSessionCache().get(path); if (o != null && o instanceof ColladaRoot) return linkRef != null ? ((ColladaRoot) o).getItemByID(linkRef) : o; URL url = WWIO.makeURL(path); if (url == null) { // See if the reference can be resolved to a local file. o = this.resolveLocalReference(path, linkRef); } // If we didn't find a local file, treat it as a remote reference. if (o == null) o = this.resolveRemoteReference(path, linkRef); if (o != null) return o; // If the reference was not resolved as a remote reference, look for a local element // identified by the // reference string. This handles the case of malformed internal references that omit the # // sign at the // beginning of the reference. return this.getItemByID(link); } catch (Exception e) { String message = Logging.getMessage("generic.UnableToResolveReference", link); Logging.logger().warning(message); } return null; }
// Raises the Save As dialog to have the user identify the location to save groups of things. public File determineSaveLocation(String dialogTitle, String defaultFolderName) { String defaultPath = this.getFileChooser().getCurrentDirectory().getPath(); if (!WWUtil.isEmpty(defaultPath)) defaultPath += File.separatorChar + defaultFolderName; File outFile; while (true) { this.getFileChooser().setDialogTitle(dialogTitle); this.getFileChooser().setSelectedFile(new File(defaultPath)); this.getFileChooser().setMultiSelectionEnabled(false); this.getFileChooser().setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); int status = this.getFileChooser().showSaveDialog(this.getFrame()); if (status != JFileChooser.APPROVE_OPTION) return null; outFile = this.getFileChooser().getSelectedFile(); if (outFile == null) { this.showMessageDialog("No location selected", "No Selection", JOptionPane.ERROR_MESSAGE); continue; } break; } if (!outFile.exists()) //noinspection ResultOfMethodCallIgnored outFile.mkdir(); return outFile; }
public AppFrame() { super( true, false, false); // Don't include the layer panel; we're using the on-screen layer tree. this.layerTree = new LayerTree(); // Set up a layer to display the on-screen layer tree in the WorldWindow. this.hiddenLayer = new RenderableLayer(); this.hiddenLayer.addRenderable(this.layerTree); this.getWwd().getModel().getLayers().add(this.hiddenLayer); // Mark the layer as hidden to prevent it being included in the layer tree's model. Including // the layer in // the tree would enable the user to hide the layer tree display with no way of bringing it // back. this.hiddenLayer.setValue(AVKey.HIDDEN, true); // Refresh the tree model with the WorldWindow's current layer list. this.layerTree.getModel().refresh(this.getWwd().getModel().getLayers()); // Add a controller to handle input events on the layer tree. this.controller = new HotSpotController(this.getWwd()); // Size the World Window to take up the space typically used by the layer panel. This // illustrates the // screen space gained by using the on-screen layer tree. Dimension size = new Dimension(1000, 600); this.setPreferredSize(size); this.pack(); WWUtil.alignComponent(null, this, AVKey.CENTER); }
/** * Unzips the sole entry in the specified zip file, and saves it in a temporary directory, and * returns a File to the temporary location. * * @param path the path to the source file. * @param suffix the suffix to give the temp file. * @return a {@link File} for the temp file. * @throws IllegalArgumentException if the <code>path</code> is <code>null</code> or empty. */ public static File unzipAndSaveToTempFile(String path, String suffix) { if (WWUtil.isEmpty(path)) { String message = Logging.getMessage("nullValue.PathIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } InputStream stream = null; try { stream = WWIO.openStream(path); ByteBuffer buffer = WWIO.readStreamToBuffer(stream); File file = WWIO.saveBufferToTempFile(buffer, WWIO.getFilename(path)); buffer = WWIO.readZipEntryToBuffer(file, null); return WWIO.saveBufferToTempFile(buffer, suffix); } catch (Exception e) { e.printStackTrace(); } finally { WWIO.closeStream(stream, path); } return null; }
/** * Build the resource map from the KML Model's <i>ResourceMap</i> element. * * @param model Model from which to create the resource map. * @return Map that relates relative paths in the COLLADA document to paths relative to the KML * document. */ protected Map<String, String> createResourceMap(KMLModel model) { Map<String, String> map = new HashMap<String, String>(); KMLResourceMap resourceMap = model.getResourceMap(); if (resourceMap == null) return Collections.emptyMap(); for (KMLAlias alias : resourceMap.getAliases()) { if (alias != null && !WWUtil.isEmpty(alias.getSourceRef()) && !WWUtil.isEmpty(alias.getTargetHref())) { map.put(alias.getSourceRef(), alias.getTargetHref()); } } return map.size() > 0 ? map : Collections.<String, String>emptyMap(); }
protected ShapeAttributes createPolygonAttributes(Color color) { ShapeAttributes attrs = new BasicShapeAttributes(); attrs.setInteriorMaterial(new Material(color)); attrs.setOutlineMaterial(new Material(WWUtil.makeColorBrighter(color))); attrs.setInteriorOpacity(0.5); attrs.setOutlineWidth(3); return attrs; }
protected void doParseEventContent(XMLEventParserContext ctx, XMLEvent event, Object... args) throws XMLStreamException { if (ctx.isStartElement(event, "Format")) { String s = ctx.getStringParser().parseString(ctx, event); if (!WWUtil.isEmpty(s)) this.formats.add(s); } else { super.doParseEventContent(ctx, event, args); } }
public WMSLayerCapabilities getLayerByName(String name) { if (WWUtil.isEmpty(name)) return null; List<WMSLayerCapabilities> namedLayers = this.getNamedLayers(); for (WMSLayerCapabilities layer : namedLayers) { if (layer.getName().equals(name)) return layer; } return null; }
/** Starts the MapPanel by creating the WWJ Map and showing it. */ public void start() { setupWWD(); setupStatusBar(); setupViewControllers(); setupSky(); // setupAnnotationToggling(); // Center the application on the screen. WWUtil.alignComponent(null, this, AVKey.CENTER); }
private void openVPFCoveragePanel(VPFDatabase db, VPFLayer layer) { VPFCoveragePanel panel = new VPFCoveragePanel(getWwd(), db); panel.setLayer(layer); JFrame frame = new JFrame(db.getName()); frame.setResizable(true); frame.setAlwaysOnTop(true); frame.add(panel); frame.pack(); WWUtil.alignComponent(this, frame, AVKey.CENTER); frame.setVisible(true); }
/** * Thread's off a task to determine whether the resource is local or remote and then retrieves it * either from disk cache or a remote server. * * @param dc the current draw context. */ protected void requestResource(DrawContext dc) { if (WorldWind.getTaskService().isFull()) return; KMLLink link = this.model.getLink(); if (link == null) return; String address = link.getAddress(dc); if (address != null) address = address.trim(); if (WWUtil.isEmpty(address)) return; WorldWind.getTaskService().addTask(new RequestTask(this, address)); }
public ViewViewVolume() { this.getContentPane().setLayout(new BorderLayout(5, 5)); this.wwp = new WWPanel(new Dimension(650, 500)); this.getContentPane().add(wwp); this.pack(); this.setResizable(true); WWUtil.alignComponent(null, this, AVKey.CENTER); this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); }
/** * Create a surface polygon from a KML GroundOverlay. * * @param tc the current {@link KMLTraversalContext}. * @param overlay the {@link gov.nasa.worldwind.ogc.kml.KMLGroundOverlay} to render as a polygon. * @throws NullPointerException if the geometry is null. * @throws IllegalArgumentException if the parent placemark or the traversal context is null. */ public KMLSurfacePolygonImpl(KMLTraversalContext tc, KMLGroundOverlay overlay) { if (tc == null) { String msg = Logging.getMessage("nullValue.TraversalContextIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (overlay == null) { String msg = Logging.getMessage("nullValue.ParentIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } this.parent = overlay; // Positions are specified either as a kml:LatLonBox or a gx:LatLonQuad Position.PositionList corners = overlay.getPositions(); this.setOuterBoundary(corners.list); if (overlay.getName() != null) this.setValue(AVKey.DISPLAY_NAME, overlay.getName()); if (overlay.getDescription() != null) this.setValue(AVKey.BALLOON_TEXT, overlay.getDescription()); if (overlay.getSnippetText() != null) this.setValue(AVKey.SHORT_DESCRIPTION, overlay.getSnippetText()); String colorStr = overlay.getColor(); if (!WWUtil.isEmpty(colorStr)) { Color color = WWUtil.decodeColorABGR(colorStr); ShapeAttributes attributes = new BasicShapeAttributes(); attributes.setDrawInterior(true); attributes.setInteriorMaterial(new Material(color)); this.setAttributes(attributes); } }
/** * Create a layer described by an XML layer description. * * @param domElement the XML element describing the layer to create. * @param params any parameters to apply when creating the layer. * @return a new layer * @throws WWUnrecognizedException if the layer type or service type given in the describing * element is unrecognized. * @see #createTiledImageLayer(org.w3c.dom.Element, gov.nasa.worldwind.avlist.AVList). */ protected Layer createFromLayerDocument(Element domElement, AVList params) { String className = WWXML.getText(domElement, "@className"); if (className != null && className.length() > 0) { Layer layer = (Layer) WorldWind.createComponent(className); String actuate = WWXML.getText(domElement, "@actuate"); layer.setEnabled(WWUtil.isEmpty(actuate) || actuate.equals("onLoad")); WWXML.invokePropertySetters(layer, domElement); return layer; } AVList props = WWXML.copyProperties(domElement, null); if (props != null) { // Copy params and add any properties for this layer to the copy if (params != null) props.setValues(params); params = props; } Layer layer; String href = WWXML.getText(domElement, "@href"); if (href != null && href.length() > 0) { Object o = this.createFromConfigSource(href, params); if (o == null) return null; if (!(o instanceof Layer)) { String msg = Logging.getMessage("LayerFactory.UnexpectedTypeForLayer", o.getClass().getName()); throw new WWRuntimeException(msg); } layer = (Layer) o; } else { String layerType = WWXML.getText(domElement, "@layerType"); if (layerType != null && layerType.equals("TiledImageLayer")) { layer = this.createTiledImageLayer(domElement, params); } else { String msg = Logging.getMessage("generic.UnrecognizedLayerType", layerType); throw new WWUnrecognizedException(msg); } } if (layer != null) { String actuate = WWXML.getText(domElement, "@actuate"); layer.setEnabled(actuate != null && actuate.equals("onLoad")); WWXML.invokePropertySetters(layer, domElement); } return layer; }
@Override protected void doParseEventAttributes(XMLEventParserContext ctx, XMLEvent event, Object... args) { Iterator iter = event.asStartElement().getAttributes(); if (iter == null) return; while (iter.hasNext()) { Attribute attr = (Attribute) iter.next(); if (attr.getName().getLocalPart().equals("name") && attr.getValue() != null) this.setName(attr.getValue()); else if (attr.getName().getLocalPart().equals("default") && attr.getValue() != null) this.setDefaultValue(attr.getValue()); else if (attr.getName().getLocalPart().equals("nearestValue") && attr.getValue() != null) { Boolean d = WWUtil.convertStringToBoolean(attr.getValue()); if (d != null) this.setNearestValue(d); } } }
/** * Resolves a reference to a remote element identified by address and identifier, where {@code * linkBase} identifies a remote document, and {@code linkRef} is the id of the desired element. * This method retrieves resources asynchronously using the {@link * gov.nasa.worldwind.cache.FileStore}. * * <p>The return value is null if the file is not yet available in the FileStore. If {@code * linkBase} refers to a COLLADA file and {@code linkRef} is non-null, the return value is the * element identified by {@code linkRef}. If {@code linkBase} refers to a COLLADA file and {@code * linkRef} is null, the return value is a parsed {@link ColladaRoot} for the COLLADA file * identified by {@code linkBase}. Otherwise the return value is a {@link URL} to the file in the * file cache. * * @param linkBase the address of the document containing the requested element. * @param linkRef the element's identifier. * @return URL to the requested file, parsed ColladaRoot, or COLLADA element. Returns null if the * document is not yet available in the FileStore. * @throws IllegalArgumentException if the {@code linkBase} is null. */ public Object resolveRemoteReference(String linkBase, String linkRef) { if (linkBase == null) { String message = Logging.getMessage("nullValue.DocumentSourceIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } try { // See if it's in the cache. If not, requestFile will start another thread to retrieve it and // return null. URL url = WorldWind.getDataFileStore().requestFile(linkBase); if (url == null) return null; // It's in the cache. If it's a COLLADA file try to parse it so we can search for the // specified reference. // If it's not COLLADA, just return the url for the cached file. String contentType = WorldWind.getDataFileStore().getContentType(linkBase); if (contentType == null) { String suffix = WWIO.getSuffix(linkBase.split(";")[0]); // strip of trailing garbage if (!WWUtil.isEmpty(suffix)) contentType = WWIO.makeMimeTypeForSuffix(suffix); } if (!this.canParseContentType(contentType)) return url; // If the file is a COLLADA document, attempt to open it. We can't open it as a File with // createAndParse // because the ColladaRoot that will be created needs to have the remote address in order to // resolve any // relative references within it. ColladaRoot refRoot = this.parseCachedColladaFile(url, linkBase); // Add the parsed file to the session cache so it doesn't have to be parsed again. WorldWind.getSessionCache().put(linkBase, refRoot); // Now check the newly opened COLLADA file for the referenced item, if a reference was // specified. if (linkRef != null) return refRoot.getItemByID(linkRef); else return refRoot; } catch (Exception e) { String message = Logging.getMessage("generic.UnableToResolveReference", linkBase + "/" + linkRef); Logging.logger().warning(message); return null; } }
public void openLink(String link) { if (WWUtil.isEmpty(link)) return; try { try { // See if the link is a URL, and invoke the browser if it is URL url = new URL(link.replace(" ", "%20")); Desktop.getDesktop().browse(url.toURI()); return; } catch (MalformedURLException ignored) { // just means that the link is not a URL } // It's not a URL, so see if it's a file and invoke the desktop to open it if it is. File file = new File(link); if (file.exists()) { Desktop.getDesktop().open(new File(link)); return; } String message = "Cannot open resource. It's not a valid file or URL."; Util.getLogger().log(Level.SEVERE, message); this.showErrorDialog(null, "No Reconocido V\u00ednculo", message); } catch (UnsupportedOperationException e) { String message = "Unable to open resource.\n" + link + (e.getMessage() != null ? "\n" + e.getMessage() : ""); Util.getLogger().log(Level.SEVERE, message, e); this.showErrorDialog(e, "Error Opening Resource", message); } catch (IOException e) { String message = "I/O error while opening resource.\n" + link + (e.getMessage() != null ? ".\n" + e.getMessage() : ""); Util.getLogger().log(Level.SEVERE, message, e); this.showErrorDialog(e, "I/O Error", message); } catch (Exception e) { String message = "Error attempting to open resource.\n" + link + (e.getMessage() != null ? "\n" + e.getMessage() : ""); Util.getLogger().log(Level.SEVERE, message); this.showMessageDialog(message, "Error Opening Resource", JOptionPane.ERROR_MESSAGE); } }
public void applyOperations() { this.updatesApplied = true; if (WWUtil.isEmpty(this.getTargetHref())) return; if (this.operations == null || this.operations.size() == 0) return; Object o = this.getRoot().resolveReference(this.getTargetHref()); if (o == null || !(o instanceof KMLRoot)) return; KMLRoot targetRoot = (KMLRoot) o; for (KMLUpdateOperation operation : this.operations) { operation.applyOperation(targetRoot); } targetRoot.firePropertyChange(AVKey.UPDATED, null, this); }
public void selected(SelectEvent event) { try { if (event.isRollover()) { if (this.lastSelectedObject == event.getTopObject()) return; // same thing selected if (this.lastSelectedObject != null) { this.hideAnnotationPanel(); this.lastSelectedObject = null; } if (event.getTopObject() != null && event.getTopObject() instanceof AVList) { String annoText = ((AVList) event.getTopObject()).getStringValue(Constants.INFO_PANEL_TEXT); if (!WWUtil.isEmpty(annoText)) { this.lastSelectedObject = (AVList) event.getTopObject(); this.showAnnotationPanel(annoText); } } } } catch (Exception e) { // Wrap the handler in a try/catch to keep exceptions from bubbling up Util.getLogger().warning(e.getMessage() != null ? e.getMessage() : e.toString()); } }
/** * Create an screen image. * * @param tc the current {@link KMLTraversalContext}. * @param overlay the <i>Overlay</i> element containing. * @throws NullPointerException if the traversal context is null. * @throws IllegalArgumentException if the parent overlay or the traversal context is null. */ public KMLScreenImageImpl(KMLTraversalContext tc, KMLScreenOverlay overlay) { this.parent = overlay; if (tc == null) { String msg = Logging.getMessage("nullValue.TraversalContextIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } if (overlay == null) { String msg = Logging.getMessage("nullValue.ParentIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } KMLVec2 xy = this.parent.getScreenXY(); if (xy != null) { this.screenOffset = new Offset( xy.getX(), xy.getY(), KMLUtil.kmlUnitsToWWUnits(xy.getXunits()), KMLUtil.kmlUnitsToWWUnits(xy.getYunits())); } xy = this.parent.getOverlayXY(); if (xy != null) { this.imageOffset = new Offset( xy.getX(), xy.getY(), KMLUtil.kmlUnitsToWWUnits(xy.getXunits()), KMLUtil.kmlUnitsToWWUnits(xy.getYunits())); } this.setRotation(overlay.getRotation()); xy = this.parent.getRotationXY(); if (xy != null) { setRotationOffset( new Offset( xy.getX(), xy.getY(), KMLUtil.kmlUnitsToWWUnits(xy.getXunits()), KMLUtil.kmlUnitsToWWUnits(xy.getYunits()))); } String colorStr = overlay.getColor(); if (colorStr != null) { Color color = WWUtil.decodeColorABGR(colorStr); this.setColor(color); } // Compute desired image size, and the scale factor that will make it that size KMLVec2 kmlSize = this.parent.getSize(); if (kmlSize != null) { Size size = new Size(); size.setWidth( getSizeMode(kmlSize.getX()), kmlSize.getX(), KMLUtil.kmlUnitsToWWUnits(kmlSize.getXunits())); size.setHeight( getSizeMode(kmlSize.getY()), kmlSize.getY(), KMLUtil.kmlUnitsToWWUnits(kmlSize.getYunits())); this.setSize(size); } }
protected void doDrawOnTo(BufferedImageRaster canvas) { Sector sector = this.getSector(); if (null == sector) { String message = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (!sector.intersects(canvas.getSector())) { return; } java.awt.Graphics2D g2d = null; java.awt.Shape prevClip = null; java.awt.Composite prevComposite = null; java.lang.Object prevInterpolation = null, prevAntialiasing = null; try { int canvasWidth = canvas.getWidth(); int canvasHeight = canvas.getHeight(); // Apply the transform that correctly maps the image onto the canvas. java.awt.geom.AffineTransform transform = this.computeSourceToDestTransform( this.getWidth(), this.getHeight(), this.getSector(), canvasWidth, canvasHeight, canvas.getSector()); AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR); Rectangle2D rect = op.getBounds2D(this.getBufferedImage()); int clipWidth = (int) Math.ceil((rect.getMaxX() >= canvasWidth) ? canvasWidth : rect.getMaxX()); int clipHeight = (int) Math.ceil((rect.getMaxY() >= canvasHeight) ? canvasHeight : rect.getMaxY()); if (clipWidth <= 0 || clipHeight <= 0) { return; } g2d = canvas.getGraphics(); prevClip = g2d.getClip(); prevComposite = g2d.getComposite(); prevInterpolation = g2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION); prevAntialiasing = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING); // Set the alpha composite for appropriate alpha blending. g2d.setComposite(java.awt.AlphaComposite.SrcOver); g2d.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.drawImage(this.getBufferedImage(), transform, null); } // catch (java.awt.image.ImagingOpException ioe) // { // // If we catch a ImagingOpException, then the transformed image has a width or // height of 0. // // This indicates that there is no intersection between the source image and the // canvas, // // or the intersection is smaller than one pixel. // } // catch (java.awt.image.RasterFormatException rfe) // { // // If we catch a RasterFormatException, then the transformed image has a width or // height of 0. // // This indicates that there is no intersection between the source image and the // canvas, // // or the intersection is smaller than one pixel. // } catch (Throwable t) { String reason = WWUtil.extractExceptionReason(t); Logging.logger().log(java.util.logging.Level.SEVERE, reason, t); } finally { // Restore the previous clip, composite, and transform. try { if (null != g2d) { if (null != prevClip) g2d.setClip(prevClip); if (null != prevComposite) g2d.setComposite(prevComposite); if (null != prevInterpolation) g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, prevInterpolation); if (null != prevAntialiasing) g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, prevAntialiasing); } } catch (Throwable t) { Logging.logger().log(java.util.logging.Level.FINEST, WWUtil.extractExceptionReason(t), t); } } }
/** * Export the placemark attributes to KML as a {@code <Style>} element. The {@code output} object * will receive the data. This object must be one of: java.io.Writer<br> * java.io.OutputStream<br> * javax.xml.stream.XMLStreamWriter * * @param output Object to receive the generated KML. * @throws XMLStreamException If an exception occurs while writing the KML * @see #export(String, Object) */ protected void exportAsKML(Object output) throws XMLStreamException { XMLStreamWriter xmlWriter = null; XMLOutputFactory factory = XMLOutputFactory.newInstance(); boolean closeWriterWhenFinished = true; if (output instanceof XMLStreamWriter) { xmlWriter = (XMLStreamWriter) output; closeWriterWhenFinished = false; } else if (output instanceof Writer) { xmlWriter = factory.createXMLStreamWriter((Writer) output); } else if (output instanceof OutputStream) { xmlWriter = factory.createXMLStreamWriter((OutputStream) output); } if (xmlWriter == null) { String message = Logging.getMessage("Export.UnsupportedOutputObject"); Logging.logger().warning(message); throw new IllegalArgumentException(message); } xmlWriter.writeStartElement("Style"); // Line style xmlWriter.writeStartElement("LineStyle"); final Color lineColor = this.getOutlineMaterial().getDiffuse(); if (lineColor != null) { xmlWriter.writeStartElement("color"); xmlWriter.writeCharacters(KMLExportUtil.stripHexPrefix(WWUtil.encodeColorABGR(lineColor))); xmlWriter.writeEndElement(); xmlWriter.writeStartElement("colorMode"); xmlWriter.writeCharacters("normal"); xmlWriter.writeEndElement(); } final Double lineWidth = this.getOutlineWidth(); if (lineWidth != null) { xmlWriter.writeStartElement("width"); xmlWriter.writeCharacters(Double.toString(lineWidth)); xmlWriter.writeEndElement(); } xmlWriter.writeEndElement(); // LineStyle // Poly style xmlWriter.writeStartElement("PolyStyle"); final Color fillColor = this.getInteriorMaterial().getDiffuse(); if (fillColor != null) { xmlWriter.writeStartElement("color"); xmlWriter.writeCharacters(KMLExportUtil.stripHexPrefix(WWUtil.encodeColorABGR(fillColor))); xmlWriter.writeEndElement(); xmlWriter.writeStartElement("colorMode"); xmlWriter.writeCharacters("normal"); xmlWriter.writeEndElement(); } xmlWriter.writeStartElement("fill"); xmlWriter.writeCharacters(kmlBoolean(isDrawInterior())); xmlWriter.writeEndElement(); xmlWriter.writeStartElement("outline"); xmlWriter.writeCharacters(kmlBoolean(isDrawOutline())); xmlWriter.writeEndElement(); xmlWriter.writeEndElement(); // PolyStyle xmlWriter.writeEndElement(); // Style xmlWriter.flush(); if (closeWriterWhenFinished) xmlWriter.close(); }