All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwind.render.SurfaceSector Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show newest version
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */
package gov.nasa.worldwind.render;

import gov.nasa.worldwind.Exportable;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.ogc.kml.KMLConstants;
import gov.nasa.worldwind.ogc.kml.impl.KMLExportUtil;
import gov.nasa.worldwind.util.*;

import javax.xml.stream.*;
import java.io.*;
import java.util.*;

/**
 * @author dcollins
 * @version $Id: SurfaceSector.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class SurfaceSector extends AbstractSurfaceShape implements Exportable
{
    protected Sector sector = Sector.EMPTY_SECTOR;

    /** Constructs a new surface sector with the default attributes and the {@link gov.nasa.worldwind.geom.Sector#EMPTY_SECTOR}. */
    public SurfaceSector()
    {
    }

    /**
     * Constructs a new surface sector with the specified normal (as opposed to highlight) attributes and the {@link
     * gov.nasa.worldwind.geom.Sector#EMPTY_SECTOR}. Modifying the attribute reference after calling this constructor
     * causes this shape's appearance to change accordingly.
     *
     * @param normalAttrs the normal attributes. May be null, in which case default attributes are used.
     */
    public SurfaceSector(ShapeAttributes normalAttrs)
    {
        super(normalAttrs);
    }

    /**
     * Constructs a new surface sector with the specified sector.
     *
     * @param sector the shape's sector.
     *
     * @throws IllegalArgumentException if the sector is null.
     */
    public SurfaceSector(Sector sector)
    {
        if (sector == null)
        {
            String message = Logging.getMessage("nullValue.SectorIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.sector = sector;
    }

    /**
     * Constructs a new surface sector with the specified normal (as opposed to highlight) attributes and the specified
     * sector. Modifying the attribute reference after calling this constructor causes this shape's appearance to change
     * accordingly.
     *
     * @param normalAttrs the normal attributes. May be null, in which case default attributes are used.
     * @param sector      the shape's sector.
     *
     * @throws IllegalArgumentException if the sector is null.
     */
    public SurfaceSector(ShapeAttributes normalAttrs, Sector sector)
    {
        super(normalAttrs);

        if (sector == null)
        {
            String message = Logging.getMessage("nullValue.SectorIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.sector = sector;
    }

    public Sector getSector()
    {
        return this.sector;
    }

    public void setSector(Sector sector)
    {
        if (sector == null)
        {
            String message = Logging.getMessage("nullValue.SectorIsNull");
            Logging.logger().severe(message);
            throw new IllegalArgumentException(message);
        }

        this.sector = sector;
        this.onShapeChanged();
    }

    public Position getReferencePosition()
    {
        return new Position(this.sector.getCentroid(), 0);
    }

    public Iterable getLocations(Globe globe)
    {
        if (this.sector.equals(Sector.EMPTY_SECTOR))
            return null;

        LatLon[] locations = new LatLon[5];
        System.arraycopy(this.sector.getCorners(), 0, locations, 0, 4);
        locations[4] = locations[0];

        return Arrays.asList(locations);
    }

    protected List> createGeometry(Globe globe, SurfaceTileDrawContext sdc)
    {
        Iterable originalLocations = this.getLocations(globe);
        if (originalLocations == null)
            return null;

        ArrayList drawLocations = new ArrayList();
        double edgeIntervalsPerDegree = this.computeEdgeIntervalsPerDegree(sdc);
        this.generateIntermediateLocations(originalLocations, edgeIntervalsPerDegree, false, drawLocations);

        ArrayList> geom = new ArrayList>();
        geom.add(drawLocations);

        return geom;
    }

    protected void doMoveTo(Position oldReferencePosition, Position newReferencePosition)
    {
        LatLon[] locations = new LatLon[]
            {
                new LatLon(this.sector.getMinLatitude(), this.sector.getMinLongitude()),
                new LatLon(this.sector.getMaxLatitude(), this.sector.getMaxLongitude())
            };

        LatLon[] newLocations = new LatLon[2];
        for (int i = 0; i < 2; i++)
        {
            Angle heading = LatLon.greatCircleAzimuth(oldReferencePosition, locations[i]);
            Angle pathLength = LatLon.greatCircleDistance(oldReferencePosition, locations[i]);
            newLocations[i] = LatLon.greatCircleEndPosition(newReferencePosition, heading, pathLength);
        }

        this.setSector(new Sector(
            newLocations[0].getLatitude(), newLocations[1].getLatitude(),
            newLocations[0].getLongitude(), newLocations[1].getLongitude()));
    }

    //**************************************************************//
    //******************** Restorable State  ***********************//
    //**************************************************************//

    protected void doGetRestorableState(RestorableSupport rs, RestorableSupport.StateObject context)
    {
        super.doGetRestorableState(rs, context);

        rs.addStateValueAsSector(context, "sector", this.getSector());
    }

    protected void doRestoreState(RestorableSupport rs, RestorableSupport.StateObject context)
    {
        super.doRestoreState(rs, context);

        Sector sector = rs.getStateValueAsSector(context, "sector");
        if (sector != null)
            this.setSector(sector);
    }

    protected void legacyRestoreState(RestorableSupport rs, RestorableSupport.StateObject context)
    {
        super.legacyRestoreState(rs, context);

        // Previous versions of SurfaceSector would have stored the locations produced by treating the sector as a list
        // of polygon locations. To restore an shape saved from the previous version, we compute the bounding sector of
        // those locations to define a sector.
        List locations = rs.getStateValueAsLatLonList(context, "locations");
        if (locations != null)
            this.setSector(Sector.boundingSector(locations));
    }

    /**
     * Export the sector to KML as a {@code } element. The {@code output} object will receive the data. This
     * object must be one of: java.io.Writer java.io.OutputStream javax.xml.stream.XMLStreamWriter
     *
     * @param output Object to receive the generated KML.
     *
     * @throws XMLStreamException If an exception occurs while writing the KML
     * @throws IOException        if an exception occurs while exporting the data.
     * @see #export(String, Object)
     */
    protected void exportAsKML(Object output) throws IOException, 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("Placemark");

        String property = (String) getValue(AVKey.DISPLAY_NAME);
        if (property != null)
        {
            xmlWriter.writeStartElement("name");
            xmlWriter.writeCharacters(property);
            xmlWriter.writeEndElement();
        }

        xmlWriter.writeStartElement("visibility");
        xmlWriter.writeCharacters(KMLExportUtil.kmlBoolean(this.isVisible()));
        xmlWriter.writeEndElement();

        String shortDescription = (String) getValue(AVKey.SHORT_DESCRIPTION);
        if (shortDescription != null)
        {
            xmlWriter.writeStartElement("Snippet");
            xmlWriter.writeCharacters(shortDescription);
            xmlWriter.writeEndElement();
        }

        String description = (String) getValue(AVKey.BALLOON_TEXT);
        if (description != null)
        {
            xmlWriter.writeStartElement("description");
            xmlWriter.writeCharacters(description);
            xmlWriter.writeEndElement();
        }

        final ShapeAttributes normalAttributes = this.getAttributes();
        final ShapeAttributes highlightAttributes = this.getHighlightAttributes();

        // Write style map
        if (normalAttributes != null || highlightAttributes != null)
        {
            xmlWriter.writeStartElement("StyleMap");
            KMLExportUtil.exportAttributesAsKML(xmlWriter, KMLConstants.NORMAL, normalAttributes);
            KMLExportUtil.exportAttributesAsKML(xmlWriter, KMLConstants.HIGHLIGHT, highlightAttributes);
            xmlWriter.writeEndElement(); // StyleMap
        }

        // Write geometry
        xmlWriter.writeStartElement("Polygon");

        xmlWriter.writeStartElement("extrude");
        xmlWriter.writeCharacters("0");
        xmlWriter.writeEndElement();

        xmlWriter.writeStartElement("altitudeMode");
        xmlWriter.writeCharacters("clampToGround");
        xmlWriter.writeEndElement();

        Sector sector = this.getSector();
        LatLon[] corners = sector.getCorners();

        xmlWriter.writeStartElement("outerBoundaryIs");
        KMLExportUtil.exportBoundaryAsLinearRing(xmlWriter, Arrays.asList(corners), null);
        xmlWriter.writeEndElement(); // outerBoundaryIs

        xmlWriter.writeEndElement(); // Polygon
        xmlWriter.writeEndElement(); // Placemark

        xmlWriter.flush();
        if (closeWriterWhenFinished)
            xmlWriter.close();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy