diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml index 4afb9b93a0..2e5268b58c 100644 --- a/nbproject/build-impl.xml +++ b/nbproject/build-impl.xml @@ -1686,6 +1686,7 @@ is divided into following sections: + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties index ec6652016b..80786b06c2 100644 --- a/nbproject/genfiles.properties +++ b/nbproject/genfiles.properties @@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=f85dc8f2@1.95.0.48 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=6106e3d1 -nbproject/build-impl.xml.script.CRC32=f2cfd8e0 -nbproject/build-impl.xml.stylesheet.CRC32=f89f7d21@1.95.0.48 +nbproject/build-impl.xml.script.CRC32=8e6690c6 +nbproject/build-impl.xml.stylesheet.CRC32=d549e5cc@1.97.0.48 diff --git a/src/config/worldwind.xml b/src/config/worldwind.xml index ee08552899..c11a2c1527 100644 --- a/src/config/worldwind.xml +++ b/src/config/worldwind.xml @@ -1,31 +1,31 @@ +~ Copyright 2006-2009, 2017, 2020 United States Government, as represented by the +~ Administrator of the National Aeronautics and Space Administration. +~ All rights reserved. +~ +~ The NASA World Wind Java (WWJ) platform is licensed under the Apache License, +~ Version 2.0 (the "License"); you may not use this file except in compliance +~ with the License. You may obtain a copy of the License at +~ http://www.apache.org/licenses/LICENSE-2.0 +~ +~ Unless required by applicable law or agreed to in writing, software distributed +~ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +~ CONDITIONS OF ANY KIND, either express or implied. See the License for the +~ specific language governing permissions and limitations under the License. +~ +~ NASA World Wind Java (WWJ) also contains the following 3rd party Open Source +~ software: +~ +~ Jackson Parser – Licensed under Apache 2.0 +~ GDAL – Licensed under MIT +~ JOGL – Licensed under Berkeley Software Distribution (BSD) +~ Gluegen – Licensed under Berkeley Software Distribution (BSD) +~ +~ A complete listing of 3rd Party software notices and licenses included in +~ NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party +~ notices and licenses PDF found in code directory. +--> @@ -116,10 +116,10 @@ +See https://goworldwind.org/developers-guide/symbology/tactical-symbols/#offline-use for more information on how +to configure a local symbol repository. +Examples: http://myserver.com/milstd2525/ (web server) + jar:file:milstd2525-symbols.zip! (local zip archive) --> \ No newline at end of file diff --git a/src/gov/nasa/worldwind/formats/shapefile/Shapefile.java b/src/gov/nasa/worldwind/formats/shapefile/Shapefile.java index 3dca302b66..45bd27565b 100644 --- a/src/gov/nasa/worldwind/formats/shapefile/Shapefile.java +++ b/src/gov/nasa/worldwind/formats/shapefile/Shapefile.java @@ -25,7 +25,6 @@ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party * notices and licenses PDF found in code directory. */ - package gov.nasa.worldwind.formats.shapefile; import com.jogamp.common.nio.Buffers; @@ -46,11 +45,14 @@ import java.util.logging.Level; /** - * Parses an ESRI Shapefile (.shp) and provides access to its contents. For details on the Shapefile format see the ESRI - * documentation at http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf. + * Parses an ESRI Shapefile (.shp) and provides access to its contents. For + * details on the Shapefile format see the ESRI documentation at + * http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf. *

- * The Shapefile provides a streaming interface for parsing a Shapefile's contents. The streaming interface enables - * applications to read Shapefiles that do not fit in memory. A typical usage pattern is as follows:


+ * The Shapefile provides a streaming interface for parsing a Shapefile's
+ * contents. The streaming interface enables applications to read Shapefiles
+ * that do not fit in memory. A typical usage pattern is as follows:
+ * 

  * Object source = "MyShapefile.shp";
  * Shapefile sf = new Shapefile(source);
  * try
@@ -67,49 +69,70 @@
  * }
  * 
*

- * The source Shapefile may be accompanied by an optional index file, attribute file, and projection file. Shapefile - * constructors that accept a generic source such as {@link #Shapefile(Object)} expect accompanying files to be in the - * same logical folder as the Shapefile, have the same filename as the Shapefile, and have suffixes ".shx", ".dbf", and - * ".prj" respectively. If any of these files do not exist, or cannot be read for any reason, the Shapefile opens - * without that information. Alternatively, the Shapefile can be constructed by providing a direct {@link - * java.io.InputStream} to any of the accompanying sources by using the InputStream based constructors, such as {@link + * The source Shapefile may be accompanied by an optional index file, attribute + * file, and projection file. Shapefile constructors that accept a generic + * source such as {@link #Shapefile(Object)} expect accompanying files to be in + * the same logical folder as the Shapefile, have the same filename as the + * Shapefile, and have suffixes ".shx", ".dbf", and ".prj" respectively. If any + * of these files do not exist, or cannot be read for any reason, the Shapefile + * opens without that information. Alternatively, the Shapefile can be + * constructed by providing a direct {@link + * java.io.InputStream} to any of the accompanying sources by using the + * InputStream based constructors, such as {@link * #Shapefile(java.io.InputStream, java.io.InputStream, java.io.InputStream, java.io.InputStream)}. *

Coordinate System

*

- * The Shapefile's coordinate system affects how the Shapefile's point coordinates are interpreted as follows:

    - *
  • Unspecified - coordinates are not changed.
  • Geographic - coordinates are validated during parsing. - * Coordinates outside the standard range of +90/-90 latitude and +180/-180 longitude cause the Shapefile to throw an - * exception during construction if the Shapefile's header contains an invalid coordinate, or in {@link - * #readNextRecord()} if any of the Shapefile's records contain an invalid coordinate.
  • Universal Transverse - * Mercator (UTM) - UTM coordinates are converted to geographic coordinates during parsing.
  • Unsupported - the - * Shapefile throws a {@link gov.nasa.worldwind.exception.WWRuntimeException} during construction.
+ * The Shapefile's coordinate system affects how the Shapefile's point + * coordinates are interpreted as follows:
    + *
  • Unspecified - coordinates are not changed.
  • Geographic - + * coordinates are validated during parsing. Coordinates outside the standard + * range of +90/-90 latitude and +180/-180 longitude cause the Shapefile to + * throw an exception during construction if the Shapefile's header contains an + * invalid coordinate, or in {@link + * #readNextRecord()} if any of the Shapefile's records contain an invalid + * coordinate.
  • Universal Transverse Mercator (UTM) - UTM coordinates + * are converted to geographic coordinates during parsing.
  • Unsupported + * - the Shapefile throws a + * {@link gov.nasa.worldwind.exception.WWRuntimeException} during + * construction.
*

- * The Shapefile's coordinate system can be specified in either an accompanying projection file, or by specifying the - * coordinate system parameters in an {@link gov.nasa.worldwind.avlist.AVList} during Shapefile's construction. The - * Shapefile gives priority to the AVList if an accompanying projection file is available and AVList projection - * parameters are specified. If an accompanying projection file is available, the Shapefile attempts to parse the - * projection file as an OGC coordinate system encoded in well-known text format. For details, see the OGC Coordinate - * Transform Service (CT) specification at http://www.opengeospatial.org/standards/ct. - * The Shapefile expects the AVList specifying its coordinate system parameters to contain the following properties: + * The Shapefile's coordinate system can be specified in either an accompanying + * projection file, or by specifying the coordinate system parameters in an + * {@link gov.nasa.worldwind.avlist.AVList} during Shapefile's construction. The + * Shapefile gives priority to the AVList if an accompanying projection file is + * available and AVList projection parameters are specified. If an accompanying + * projection file is available, the Shapefile attempts to parse the projection + * file as an OGC coordinate system encoded in well-known text format. For + * details, see the OGC Coordinate Transform Service (CT) specification at + * http://www.opengeospatial.org/standards/ct. + * The Shapefile expects the AVList specifying its coordinate system parameters + * to contain the following properties: *

  • {@link gov.nasa.worldwind.avlist.AVKey#COORDINATE_SYSTEM} - either {@link - * gov.nasa.worldwind.avlist.AVKey#COORDINATE_SYSTEM_GEOGRAPHIC} or {@link gov.nasa.worldwind.avlist.AVKey#COORDINATE_SYSTEM_PROJECTED}.
  • - *
  • {@link gov.nasa.worldwind.avlist.AVKey#PROJECTION_ZONE} - the UTM zone (if coordinate system projection is UTM); - * an integer in the range 1-60.
  • {@link gov.nasa.worldwind.avlist.AVKey#PROJECTION_HEMISPHERE} - the UTM - * hemisphere (if coordinate system is UTM); either {@link gov.nasa.worldwind.avlist.AVKey#NORTH} or {@link + * gov.nasa.worldwind.avlist.AVKey#COORDINATE_SYSTEM_GEOGRAPHIC} or + * {@link gov.nasa.worldwind.avlist.AVKey#COORDINATE_SYSTEM_PROJECTED}.
  • + *
  • {@link gov.nasa.worldwind.avlist.AVKey#PROJECTION_ZONE} - the UTM zone + * (if coordinate system projection is UTM); an integer in the range 1-60.
  • + *
  • {@link gov.nasa.worldwind.avlist.AVKey#PROJECTION_HEMISPHERE} - the UTM + * hemisphere (if coordinate system is UTM); either + * {@link gov.nasa.worldwind.avlist.AVKey#NORTH} or {@link * gov.nasa.worldwind.avlist.AVKey#SOUTH}.
*

- * Subclasses can override how the Shapefile reads and interprets its coordinate system. Override {@link - * #readCoordinateSystem()} and {@link #validateCoordinateSystem(gov.nasa.worldwind.avlist.AVList)} to change how the - * Shapefile parses an accompanying projection file and validates the coordinate system parameters. Override - * {@link #readBoundingRectangle(java.nio.ByteBuffer)} - * and {@link #readPoints(gov.nasa.worldwind.formats.shapefile.ShapefileRecord,java.nio.ByteBuffer)} to change how the - * Shapefile's point coordinates are interpreted according to its coordinate system. + * Subclasses can override how the Shapefile reads and interprets its coordinate + * system. Override {@link + * #readCoordinateSystem()} and + * {@link #validateCoordinateSystem(gov.nasa.worldwind.avlist.AVList)} to change + * how the Shapefile parses an accompanying projection file and validates the + * coordinate system parameters. Override + * {@link #readBoundingRectangle(java.nio.ByteBuffer)} and + * {@link #readPoints(gov.nasa.worldwind.formats.shapefile.ShapefileRecord,java.nio.ByteBuffer)} + * to change how the Shapefile's point coordinates are interpreted according to + * its coordinate system. * * @author Patrick Murris * @version $Id: Shapefile.java 3426 2015-09-30 23:19:16Z dcollins $ */ -public class Shapefile extends AVListImpl implements Closeable, Exportable -{ +public class Shapefile extends AVListImpl implements Closeable, Exportable { + protected static final int FILE_CODE = 0x0000270A; protected static final int HEADER_LENGTH = 100; @@ -118,22 +141,22 @@ public class Shapefile extends AVListImpl implements Closeable, Exportable protected static final String ATTRIBUTE_FILE_SUFFIX = ".dbf"; protected static final String PROJECTION_FILE_SUFFIX = ".prj"; - protected static final String[] SHAPE_CONTENT_TYPES = - { - "application/shp", - "application/octet-stream" - }; - protected static final String[] INDEX_CONTENT_TYPES = - { - "application/shx", - "application/octet-stream" - }; - protected static final String[] PROJECTION_CONTENT_TYPES = - { - "application/prj", - "application/octet-stream", - "text/plain" - }; + protected static final String[] SHAPE_CONTENT_TYPES + = { + "application/shp", + "application/octet-stream" + }; + protected static final String[] INDEX_CONTENT_TYPES + = { + "application/shx", + "application/octet-stream" + }; + protected static final String[] PROJECTION_CONTENT_TYPES + = { + "application/prj", + "application/octet-stream", + "text/plain" + }; public static final String SHAPE_NULL = "gov.nasa.worldwind.formats.shapefile.Shapefile.ShapeNull"; public static final String SHAPE_POINT = "gov.nasa.worldwind.formats.shapefile.Shapefile.ShapePoint"; @@ -154,21 +177,21 @@ public class Shapefile extends AVListImpl implements Closeable, Exportable public static final String SHAPE_MULTI_PATCH = "gov.nasa.worldwind.formats.shapefile.Shapefile.ShapeMultiPatch"; protected static List measureTypes = new ArrayList(Arrays.asList( - Shapefile.SHAPE_POINT_M, Shapefile.SHAPE_POINT_Z, - Shapefile.SHAPE_MULTI_POINT_M, Shapefile.SHAPE_MULTI_POINT_Z, - Shapefile.SHAPE_POLYLINE_M, Shapefile.SHAPE_POLYLINE_Z, - Shapefile.SHAPE_POLYGON_M, Shapefile.SHAPE_POLYGON_Z + Shapefile.SHAPE_POINT_M, Shapefile.SHAPE_POINT_Z, + Shapefile.SHAPE_MULTI_POINT_M, Shapefile.SHAPE_MULTI_POINT_Z, + Shapefile.SHAPE_POLYLINE_M, Shapefile.SHAPE_POLYLINE_Z, + Shapefile.SHAPE_POLYGON_M, Shapefile.SHAPE_POLYGON_Z )); protected static List zTypes = new ArrayList(Arrays.asList( - Shapefile.SHAPE_POINT_Z, - Shapefile.SHAPE_MULTI_POINT_Z, - Shapefile.SHAPE_POLYLINE_Z, - Shapefile.SHAPE_POLYGON_Z + Shapefile.SHAPE_POINT_Z, + Shapefile.SHAPE_MULTI_POINT_Z, + Shapefile.SHAPE_POLYLINE_Z, + Shapefile.SHAPE_POLYGON_Z )); - protected static class Header - { + protected static class Header { + public int fileCode = FILE_CODE; public int fileLength; public int version; @@ -188,9 +211,11 @@ protected static class Header protected DBaseFile attributeFile; protected boolean open; /** - * Indicates if the shapefile's point coordinates should be normalized. Defaults to false. This is used by Point - * records to determine if its points should be normalized. MultiPoint, Polyline, and Polygon records use their - * bounding rectangles to determine if they should be normalized, and therefore ignore this property. + * Indicates if the shapefile's point coordinates should be normalized. + * Defaults to false. This is used by Point records to determine if its + * points should be normalized. MultiPoint, Polyline, and Polygon records + * use their bounding rectangles to determine if they should be normalized, + * and therefore ignore this property. */ protected boolean normalizePoints; protected int numRecordsRead; @@ -200,121 +225,129 @@ protected static class Header protected MappedByteBuffer mappedShpBuffer; /** - * Opens an Shapefile from a general source. The source type may be one of the following:

  • {@link + * Opens an Shapefile from a general source. The source type may be one of + * the following:
    • {@link * java.io.InputStream}
    • {@link java.net.URL}
    • absolute {@link java.net.URI}
    • {@link - * File}
    • {@link String} containing a valid URL description or a file or resource name available on the - * classpath.
    + * File}
  • {@link String} containing a valid URL description or a + * file or resource name available on the classpath.
*

- * The source Shapefile may be accompanied by an optional index file, attribute file, and projection file. To be - * recognized by this Shapefile, accompanying files must be in the same logical folder as the Shapefile, have the - * same filename as the Shapefile, and have suffixes ".shx", ".dbf", and ".prj" respectively. If any of these files - * do not exist, or cannot be read for any reason, the Shapefile opens without that information. + * The source Shapefile may be accompanied by an optional index file, + * attribute file, and projection file. To be recognized by this Shapefile, + * accompanying files must be in the same logical folder as the Shapefile, + * have the same filename as the Shapefile, and have suffixes ".shx", + * ".dbf", and ".prj" respectively. If any of these files do not exist, or + * cannot be read for any reason, the Shapefile opens without that + * information. *

- * This throws an exception if the shapefile's coordinate system is unsupported. + * This throws an exception if the shapefile's coordinate system is + * unsupported. * * @param source the source of the shapefile. - * @param params parameter list describing metadata about the Shapefile, such as its map projection. + * @param params parameter list describing metadata about the Shapefile, + * such as its map projection. * - * @throws IllegalArgumentException if the source is null or an empty string. - * @throws WWRuntimeException if the shapefile cannot be opened for any reason, or if the shapefile's - * coordinate system is unsupported. + * @throws IllegalArgumentException if the source is null or an empty + * string. + * @throws WWRuntimeException if the shapefile cannot be opened for any + * reason, or if the shapefile's coordinate system is unsupported. */ - public Shapefile(Object source, AVList params) - { - if (source == null || WWUtil.isEmpty(source)) - { + public Shapefile(Object source, AVList params) { + if (source == null || WWUtil.isEmpty(source)) { String message = Logging.getMessage("nullValue.SourceIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - try - { + try { this.setValue(AVKey.DISPLAY_NAME, source.toString()); - if (source instanceof File) + if (source instanceof File) { this.initializeFromFile((File) source, params); - else if (source instanceof URL) + } else if (source instanceof URL) { this.initializeFromURL((URL) source, params); - else if (source instanceof InputStream) + } else if (source instanceof InputStream) { this.initializeFromStreams((InputStream) source, null, null, null, params); - else if (source instanceof String) + } else if (source instanceof String) { this.initializeFromPath((String) source, params); - else - { + } else { String message = Logging.getMessage("generic.UnrecognizedSourceType", source); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - } - catch (Exception e) - { + } catch (Exception e) { String message = Logging.getMessage("SHP.ExceptionAttemptingToReadShapefile", - this.getValue(AVKey.DISPLAY_NAME)); + this.getValue(AVKey.DISPLAY_NAME)); Logging.logger().log(Level.SEVERE, message, e); throw new WWRuntimeException(message, e); } } /** - * Opens an Shapefile from a general source. The source type may be one of the following:

  • {@link - * java.io.InputStream}
  • {@link java.net.URL}
  • {@link File}
  • {@link String} containing a - * valid URL description or a file or resource name available on the classpath.
+ * Opens an Shapefile from a general source. The source type may be one of + * the following:
  • {@link + * java.io.InputStream}
  • {@link java.net.URL}
  • + *
  • {@link File}
  • {@link String} containing a valid URL + * description or a file or resource name available on the classpath.
  • + *
*

- * The source Shapefile may be accompanied by an optional index file, attribute file, and projection file. To be - * recognized by this Shapefile, accompanying files must be in the same logical folder as the Shapefile, have the - * same filename as the Shapefile, and have suffixes ".shx", ".dbf", and ".prj" respectively. If any of these files - * do not exist, or cannot be read for any reason, the Shapefile opens without that information. + * The source Shapefile may be accompanied by an optional index file, + * attribute file, and projection file. To be recognized by this Shapefile, + * accompanying files must be in the same logical folder as the Shapefile, + * have the same filename as the Shapefile, and have suffixes ".shx", + * ".dbf", and ".prj" respectively. If any of these files do not exist, or + * cannot be read for any reason, the Shapefile opens without that + * information. *

- * This throws an exception if the shapefile's coordinate system is unsupported, or if the shapefile's coordinate - * system is unsupported. + * This throws an exception if the shapefile's coordinate system is + * unsupported, or if the shapefile's coordinate system is unsupported. * * @param source the source of the shapefile. * - * @throws IllegalArgumentException if the source is null or an empty string. - * @throws WWRuntimeException if the shapefile cannot be opened for any reason. + * @throws IllegalArgumentException if the source is null or an empty + * string. + * @throws WWRuntimeException if the shapefile cannot be opened for any + * reason. */ - public Shapefile(Object source) - { + public Shapefile(Object source) { this(source, null); } /** - * Opens a Shapefile from an InputStream, and InputStreams to its optional resources. + * Opens a Shapefile from an InputStream, and InputStreams to its optional + * resources. *

- * The source Shapefile may be accompanied optional streams to an index resource stream, an attribute resource - * stream, and a projection resource stream. If any of these streams are null or cannot be read for any reason, the - * Shapefile opens without that information. + * The source Shapefile may be accompanied optional streams to an index + * resource stream, an attribute resource stream, and a projection resource + * stream. If any of these streams are null or cannot be read for any + * reason, the Shapefile opens without that information. *

- * This throws an exception if the shapefile's coordinate system is unsupported. + * This throws an exception if the shapefile's coordinate system is + * unsupported. * * @param shpStream the shapefile geometry file stream. * @param shxStream the index file stream, can be null. * @param dbfStream the attribute file stream, can be null. * @param prjStream the projection file stream, can be null. - * @param params parameter list describing metadata about the Shapefile, such as its map projection. + * @param params parameter list describing metadata about the Shapefile, + * such as its map projection. * - * @throws IllegalArgumentException if the shapefile geometry stream shpStream is null. - * @throws WWRuntimeException if the shapefile cannot be opened for any reason, or if the shapefile's - * coordinate system is unsupported. + * @throws IllegalArgumentException if the shapefile geometry stream + * shpStream is null. + * @throws WWRuntimeException if the shapefile cannot be opened for any + * reason, or if the shapefile's coordinate system is unsupported. */ public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream, InputStream prjStream, - AVList params) - { - if (shpStream == null) - { + AVList params) { + if (shpStream == null) { String message = Logging.getMessage("nullValue.InputStreamIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - try - { + try { this.setValue(AVKey.DISPLAY_NAME, shpStream.toString()); this.initializeFromStreams(shpStream, shxStream, dbfStream, prjStream, params); - } - catch (Exception e) - { + } catch (Exception e) { String message = Logging.getMessage("SHP.ExceptionAttemptingToReadShapefile", shpStream); Logging.logger().log(Level.SEVERE, message, e); throw new WWRuntimeException(message, e); @@ -322,154 +355,173 @@ public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfSt } /** - * Opens a Shapefile from an InputStream, and InputStreams to its optional resources. + * Opens a Shapefile from an InputStream, and InputStreams to its optional + * resources. *

- * The source Shapefile may be accompanied optional streams to an index resource stream, an attribute resource - * stream, and a projection resource stream. If any of these streams are null or cannot be read for any reason, the - * Shapefile opens without that information. + * The source Shapefile may be accompanied optional streams to an index + * resource stream, an attribute resource stream, and a projection resource + * stream. If any of these streams are null or cannot be read for any + * reason, the Shapefile opens without that information. *

- * This throws an exception if the shapefile's coordinate system is unsupported. + * This throws an exception if the shapefile's coordinate system is + * unsupported. * * @param shpStream the shapefile geometry file stream. * @param shxStream the index file stream, can be null. * @param dbfStream the attribute file stream, can be null. * @param prjStream the projection file stream, can be null. * - * @throws IllegalArgumentException if the shapefile geometry stream shpStream is null. - * @throws WWRuntimeException if the shapefile cannot be opened for any reason, or if the shapefile's - * coordinate system is unsupported. + * @throws IllegalArgumentException if the shapefile geometry stream + * shpStream is null. + * @throws WWRuntimeException if the shapefile cannot be opened for any + * reason, or if the shapefile's coordinate system is unsupported. */ - public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream, InputStream prjStream) - { + public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream, InputStream prjStream) { this(shpStream, shxStream, dbfStream, prjStream, null); } /** - * Opens a Shapefile from an InputStream, and InputStreams to its optional resources. + * Opens a Shapefile from an InputStream, and InputStreams to its optional + * resources. *

- * The source Shapefile may be accompanied optional streams to an index resource stream, and an attribute resource - * stream. If any of these streams are null or cannot be read for any reason, the Shapefile opens without that - * information. + * The source Shapefile may be accompanied optional streams to an index + * resource stream, and an attribute resource stream. If any of these + * streams are null or cannot be read for any reason, the Shapefile opens + * without that information. *

- * This throws an exception if the shapefile's coordinate system is unsupported. + * This throws an exception if the shapefile's coordinate system is + * unsupported. * * @param shpStream the shapefile geometry file stream. * @param shxStream the index file stream, can be null. * @param dbfStream the attribute file stream, can be null. - * @param params parameter list describing metadata about the Shapefile, such as its map projection. + * @param params parameter list describing metadata about the Shapefile, + * such as its map projection. * - * @throws IllegalArgumentException if the shapefile geometry stream shpStream is null. - * @throws WWRuntimeException if the shapefile cannot be opened for any reason, or if the shapefile's - * coordinate system is unsupported. + * @throws IllegalArgumentException if the shapefile geometry stream + * shpStream is null. + * @throws WWRuntimeException if the shapefile cannot be opened for any + * reason, or if the shapefile's coordinate system is unsupported. */ - public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream, AVList params) - { + public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream, AVList params) { this(shpStream, shxStream, dbfStream, null, params); } /** - * Opens a Shapefile from an InputStream, and InputStreams to its optional resources. + * Opens a Shapefile from an InputStream, and InputStreams to its optional + * resources. *

- * The source Shapefile may be accompanied optional streams to an index resource stream, and an attribute resource - * stream. If any of these streams are null or cannot be read for any reason, the Shapefile opens without that - * information. + * The source Shapefile may be accompanied optional streams to an index + * resource stream, and an attribute resource stream. If any of these + * streams are null or cannot be read for any reason, the Shapefile opens + * without that information. * * @param shpStream the shapefile geometry file stream. * @param shxStream the index file stream, can be null. * @param dbfStream the attribute file stream, can be null. * - * @throws IllegalArgumentException if the shapefile geometry stream shpStream is null. - * @throws WWRuntimeException if the shapefile cannot be opened for any reason. + * @throws IllegalArgumentException if the shapefile geometry stream + * shpStream is null. + * @throws WWRuntimeException if the shapefile cannot be opened for any + * reason. */ - public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream) - { + public Shapefile(InputStream shpStream, InputStream shxStream, InputStream dbfStream) { this(shpStream, shxStream, dbfStream, null, null); } /** - * Returns the shapefile's version field, or -1 if the Shapefile failed to open. + * Returns the shapefile's version field, or -1 if the Shapefile failed to + * open. * - * @return the shapefile's version field, or -1 to denote the Shapefile failed to open. + * @return the shapefile's version field, or -1 to denote the Shapefile + * failed to open. */ - public int getVersion() - { + public int getVersion() { return this.header != null ? this.header.version : -1; } /** - * Returns the raw shapefile's length, or -1 if the Shapefile failed to open. + * Returns the raw shapefile's length, or -1 if the Shapefile failed to + * open. * - * @return the raw shapefile's length in bytes, or -1 to denote the Shapefile failed to open. + * @return the raw shapefile's length in bytes, or -1 to denote the + * Shapefile failed to open. */ - public int getLength() - { + public int getLength() { return this.header != null ? this.header.fileLength : -1; } /** - * Returns the shapefile's shape type: null if the Shapefile failed to open, otherwise one of the following symbolic - * constants:

  • {@link #SHAPE_NULL}
  • {@link #SHAPE_POINT}
  • {@link #SHAPE_MULTI_POINT}
  • - *
  • {@link #SHAPE_POLYLINE}
  • {@link #SHAPE_POLYGON}
  • {@link #SHAPE_POINT_M}
  • {@link - * #SHAPE_MULTI_POINT_M}
  • {@link #SHAPE_POLYLINE_M}
  • {@link #SHAPE_POLYGON_M}
  • {@link - * #SHAPE_POINT_Z}
  • {@link #SHAPE_MULTI_POINT_Z}
  • {@link #SHAPE_POLYLINE_Z}
  • {@link + * Returns the shapefile's shape type: null if the Shapefile failed to open, + * otherwise one of the following symbolic constants:
      + *
    • {@link #SHAPE_NULL}
    • {@link #SHAPE_POINT}
    • + *
    • {@link #SHAPE_MULTI_POINT}
    • + *
    • {@link #SHAPE_POLYLINE}
    • {@link #SHAPE_POLYGON}
    • + *
    • {@link #SHAPE_POINT_M}
    • {@link + * #SHAPE_MULTI_POINT_M}
    • {@link #SHAPE_POLYLINE_M}
    • + *
    • {@link #SHAPE_POLYGON_M}
    • {@link + * #SHAPE_POINT_Z}
    • {@link #SHAPE_MULTI_POINT_Z}
    • + *
    • {@link #SHAPE_POLYLINE_Z}
    • {@link * #SHAPE_POLYGON_Z}
    • {@link #SHAPE_MULTI_PATCH}
    * - * @return the shapefile's shape type: null if the Shapefile failed to open, othersise a symbolic constants denoting - * the type. + * @return the shapefile's shape type: null if the Shapefile failed to open, + * othersise a symbolic constants denoting the type. */ - public String getShapeType() - { + public String getShapeType() { return this.header != null ? this.header.shapeType : null; } /** - * Returns a four-element array containing the shapefile's bounding rectangle, or null if the Shapefile failed to - * open. The returned array is ordered as follows: minimum Y, maximum Y, minimum X, and maximum X. If the - * Shapefile's coordinate system is geographic, the elements can be interpreted as angular degrees in the order - * minimum latitude, maximum latitude, minimum longitude, and maximum longitude. - * - * @return the shapefile's bounding rectangle, or null to denote the Shapefile failed to open. + * Returns a four-element array containing the shapefile's bounding + * rectangle, or null if the Shapefile failed to open. The returned array is + * ordered as follows: minimum Y, maximum Y, minimum X, and maximum X. If + * the Shapefile's coordinate system is geographic, the elements can be + * interpreted as angular degrees in the order minimum latitude, maximum + * latitude, minimum longitude, and maximum longitude. + * + * @return the shapefile's bounding rectangle, or null to denote the + * Shapefile failed to open. */ - public double[] getBoundingRectangle() - { + public double[] getBoundingRectangle() { return this.header != null ? this.header.boundingRectangle : null; } /** - * Returns the number of records in the shapefile, or -1 if the number if records is unknown. + * Returns the number of records in the shapefile, or -1 if the number if + * records is unknown. * - * @return the number of records in the shapefile, or -1 to denote an unknown number of records. + * @return the number of records in the shapefile, or -1 to denote an + * unknown number of records. */ - public int getNumberOfRecords() - { + public int getNumberOfRecords() { return this.index != null ? this.index.length / 2 : -1; } /** - * Get the underlying {@link CompoundVecBuffer} describing the shapefile's points. + * Get the underlying {@link CompoundVecBuffer} describing the shapefile's + * points. * * @return the underlying {@link CompoundVecBuffer}. */ - public CompoundVecBuffer getPointBuffer() - { + public CompoundVecBuffer getPointBuffer() { return this.pointBuffer; } /** - * Returns a set of the unique attribute names associated with this shapefile's records, or null if this shapefile - * has no associated attributes. + * Returns a set of the unique attribute names associated with this + * shapefile's records, or null if this shapefile has no associated + * attributes. * - * @return a set containing the unique attribute names of this shapefile's records, or null if there are no - * attributes. + * @return a set containing the unique attribute names of this shapefile's + * records, or null if there are no attributes. */ - public Set getAttributeNames() - { - if (this.attributeFile == null) + public Set getAttributeNames() { + if (this.attributeFile == null) { return null; + } HashSet set = new HashSet(); - for (DBaseField field : this.attributeFile.getFields()) - { + for (DBaseField field : this.attributeFile.getFields()) { set.add(field.getName()); } @@ -477,43 +529,51 @@ public Set getAttributeNames() } /** - * Returns true if the Shapefile has a more records, and false if all records have been - * read. + * Returns true if the Shapefile has a more records, and + * false if all records have been read. * - * @return true if the Shapefile has a more records; false otherwise. + * @return true if the Shapefile has a more records; + * false otherwise. */ - public boolean hasNext() - { - if (!this.open || this.header == null) + public boolean hasNext() { + if (!this.open || this.header == null) { return false; + } int contentLength = this.header.fileLength - HEADER_LENGTH; return this.numBytesRead < contentLength; } /** - * Reads the Shapefile's next record and returns the result as a new {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. - * The record's type depends on the Shapefile's type, and is one of the following:
    • {@link + * Reads the Shapefile's next record and returns the result as a new + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. The + * record's type depends on the Shapefile's type, and is one of the + * following:
      • {@link * gov.nasa.worldwind.formats.shapefile.ShapefileRecordPoint} if type is {@link #SHAPE_POINT}, {@link - * #SHAPE_POINT_M} or {@link #SHAPE_POINT_Z}.
      • {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecordMultiPoint} - * if type is {@link #SHAPE_MULTI_POINT}, {@link #SHAPE_MULTI_POINT_M} or {@link #SHAPE_MULTI_POINT_Z}.
      • - *
      • {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecordPolyline} if type is {@link #SHAPE_POLYLINE}, - * {@link #SHAPE_POLYLINE_M} or {@link #SHAPE_POLYLINE_Z}.
      • {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecordPolygon} - * if type is {@link #SHAPE_POLYGON}, {@link #SHAPE_POLYGON_M} or {@link #SHAPE_POLYGON_Z}.
      + * #SHAPE_POINT_M} or {@link #SHAPE_POINT_Z}.
    • + *
    • {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecordMultiPoint} + * if type is {@link #SHAPE_MULTI_POINT}, {@link #SHAPE_MULTI_POINT_M} or + * {@link #SHAPE_MULTI_POINT_Z}.
    • + *
    • {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecordPolyline} + * if type is {@link #SHAPE_POLYLINE}, + * {@link #SHAPE_POLYLINE_M} or {@link #SHAPE_POLYLINE_Z}.
    • + *
    • {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecordPolygon} + * if type is {@link #SHAPE_POLYGON}, {@link #SHAPE_POLYGON_M} or + * {@link #SHAPE_POLYGON_Z}.
    *

    - * This throws an exception if the JVM cannot allocate enough memory to hold the buffer used to store the record's - * point coordinates. + * This throws an exception if the JVM cannot allocate enough memory to hold + * the buffer used to store the record's point coordinates. * * @return the Shapefile's next record. * - * @throws IllegalStateException if the Shapefile is closed or if the Shapefile has no more records. - * @throws WWRuntimeException if an exception occurs while reading the record. + * @throws IllegalStateException if the Shapefile is closed or if the + * Shapefile has no more records. + * @throws WWRuntimeException if an exception occurs while reading the + * record. * @see #getShapeType() */ - public ShapefileRecord nextRecord() - { - if (!this.open) - { + public ShapefileRecord nextRecord() { + if (!this.open) { String message = Logging.getMessage("SHP.ShapefileClosed", this.getStringValue(AVKey.DISPLAY_NAME)); Logging.logger().severe(message); throw new IllegalStateException(message); @@ -527,22 +587,18 @@ public ShapefileRecord nextRecord() } int contentLength = this.header.fileLength - HEADER_LENGTH; - if (contentLength <= 0 || this.numBytesRead >= contentLength) - { + if (contentLength <= 0 || this.numBytesRead >= contentLength) { String message = Logging.getMessage("SHP.NoRecords", this.getStringValue(AVKey.DISPLAY_NAME)); Logging.logger().severe(message); throw new IllegalStateException(message); } ShapefileRecord record; - try - { + try { record = this.readNextRecord(); - } - catch (Exception e) - { + } catch (Exception e) { String message = Logging.getMessage("SHP.ExceptionAttemptingToReadShapefileRecord", - this.getStringValue(AVKey.DISPLAY_NAME)); + this.getStringValue(AVKey.DISPLAY_NAME)); Logging.logger().log(Level.SEVERE, message, e); throw new WWRuntimeException(message, e); } @@ -552,37 +608,35 @@ record = this.readNextRecord(); } /** - * Closes the Shapefile, freeing any resources allocated during reading except the buffer containing the Shapefile's - * points. This closes any {@link java.io.InputStream} passed to the Shapefile during construction. Subsequent calls - * to {@link #nextRecord()} cause an IllegalStateException. + * Closes the Shapefile, freeing any resources allocated during reading + * except the buffer containing the Shapefile's points. This closes any + * {@link java.io.InputStream} passed to the Shapefile during construction. + * Subsequent calls to {@link #nextRecord()} cause an IllegalStateException. *

    - * After closing, the Shapefile's header information and point coordinates are still available. The following - * methods are safe to call:

    • {@link #getVersion()}
    • {@link #getLength()}
    • {@link - * #getShapeType()}
    • {@link #getBoundingRectangle()}
    • {@link #getNumberOfRecords()}
    • {@link + * After closing, the Shapefile's header information and point coordinates + * are still available. The following methods are safe to call:
        + *
      • {@link #getVersion()}
      • {@link #getLength()}
      • {@link + * #getShapeType()}
      • {@link #getBoundingRectangle()}
      • + *
      • {@link #getNumberOfRecords()}
      • {@link * #getPointBuffer()}
      */ - public void close() - { - if (this.shpChannel != null) - { + public void close() { + if (this.shpChannel != null) { WWIO.closeStream(this.shpChannel, null); this.shpChannel = null; } - if (this.shxChannel != null) - { + if (this.shxChannel != null) { WWIO.closeStream(this.shxChannel, null); this.shxChannel = null; } - if (this.prjChannel != null) - { + if (this.prjChannel != null) { WWIO.closeStream(this.prjChannel, null); this.prjChannel = null; } - if (this.attributeFile != null) - { + if (this.attributeFile != null) { this.attributeFile.close(); this.attributeFile = null; } @@ -596,32 +650,29 @@ public void close() /** * Returns whether the shapefile's point coordinates should be normalized. * - * @return true if the shapefile's points should be normalized; false otherwise. + * @return true if the shapefile's points should be normalized; + * false otherwise. */ - protected boolean isNormalizePoints() - { + protected boolean isNormalizePoints() { return this.normalizePoints; } /** - * Specifies if the shapefile's point coordinates should be normalized. Defaults to false. + * Specifies if the shapefile's point coordinates should be normalized. + * Defaults to false. * - * @param normalizePoints true if the shapefile's points should be normalized; false - * otherwise. + * @param normalizePoints true if the shapefile's points should + * be normalized; false otherwise. */ - protected void setNormalizePoints(boolean normalizePoints) - { + protected void setNormalizePoints(boolean normalizePoints) { this.normalizePoints = normalizePoints; } //**************************************************************// //******************** Initialization ************************// //**************************************************************// - - protected void initializeFromFile(File file, AVList params) throws IOException - { - if (!file.exists()) - { + protected void initializeFromFile(File file, AVList params) throws IOException { + if (!file.exists()) { String message = Logging.getMessage("generic.FileNotFound", file.getPath()); Logging.logger().severe(message); throw new FileNotFoundException(message); @@ -632,37 +683,36 @@ protected void initializeFromFile(File file, AVList params) throws IOException // file. Although we never change the file's bytes on disk, the file must be accessible for reading and writing // to use copy-on-write mode. Therefore files locked for writing and files stored on a read-only device // (e.g. CD, DVD) cannot be memory mapped. - if (file.canRead() && file.canWrite()) - { - try - { + if (file.canRead() && file.canWrite()) { + try { // Memory map the Shapefile in copy-on-write mode. this.mappedShpBuffer = WWIO.mapFile(file, FileChannel.MapMode.PRIVATE); Logging.logger().finer(Logging.getMessage("SHP.MemoryMappingEnabled", file.getPath())); - } - catch (IOException e) - { + } catch (IOException e) { Logging.logger().log(Level.WARNING, - Logging.getMessage("SHP.ExceptionAttemptingToMemoryMap", file.getPath()), e); + Logging.getMessage("SHP.ExceptionAttemptingToMemoryMap", file.getPath()), e); } } // If attempting to memory map the Shapefile failed, fall back on opening the file as a generic stream. Throw an // IOException if the file cannot be opened via stream. - if (this.mappedShpBuffer == null) + if (this.mappedShpBuffer == null) { this.shpChannel = Channels.newChannel(new BufferedInputStream(new FileInputStream(file))); + } // Attempt to open the optional index and projection files associated with the Shapefile. Ignore exceptions // thrown while attempting to open these optional resource streams. We wrap each source InputStream in a // BufferedInputStream because this increases read performance, even when the stream is wrapped in an NIO // Channel. InputStream shxStream = this.getFileStream(WWIO.replaceSuffix(file.getPath(), INDEX_FILE_SUFFIX)); - if (shxStream != null) + if (shxStream != null) { this.shxChannel = Channels.newChannel(WWIO.getBufferedInputStream(shxStream)); + } InputStream prjStream = this.getFileStream(WWIO.replaceSuffix(file.getPath(), PROJECTION_FILE_SUFFIX)); - if (prjStream != null) + if (prjStream != null) { this.prjChannel = Channels.newChannel(WWIO.getBufferedInputStream(prjStream)); + } // Initialize the Shapefile before opening its associated attributes file. This avoids opening the attributes // file if an exception is thrown while opening the Shapefile. @@ -671,28 +721,22 @@ protected void initializeFromFile(File file, AVList params) throws IOException // Open the shapefile attribute source as a DBaseFile. We let the DBaseFile determine how to handle source File. File dbfFile = new File(WWIO.replaceSuffix(file.getPath(), ATTRIBUTE_FILE_SUFFIX)); - if (dbfFile.exists()) - { - try - { + if (dbfFile.exists()) { + try { this.attributeFile = new DBaseFile(dbfFile); - } - catch (Exception e) - { + } catch (Exception e) { // Exception already logged by DBaseFile constructor. } } } - protected void initializeFromURL(URL url, AVList params) throws IOException - { + protected void initializeFromURL(URL url, AVList params) throws IOException { // Opening the Shapefile URL as a URL connection. Throw an IOException if the URL connection cannot be opened, // or if it's an invalid Shapefile connection. URLConnection connection = url.openConnection(); String message = this.validateURLConnection(connection, SHAPE_CONTENT_TYPES); - if (message != null) - { + if (message != null) { throw new IOException(message); } @@ -703,30 +747,28 @@ protected void initializeFromURL(URL url, AVList params) throws IOException // invalid. We wrap each source InputStream in a BufferedInputStream because this increases read performance, // even when the stream is wrapped in an NIO Channel. URLConnection shxConnection = this.getURLConnection(WWIO.replaceSuffix(url.toString(), INDEX_FILE_SUFFIX)); - if (shxConnection != null) - { + if (shxConnection != null) { message = this.validateURLConnection(shxConnection, INDEX_CONTENT_TYPES); - if (message != null) + if (message != null) { Logging.logger().warning(message); - else - { + } else { InputStream shxStream = this.getURLStream(shxConnection); - if (shxStream != null) + if (shxStream != null) { this.shxChannel = Channels.newChannel(WWIO.getBufferedInputStream(shxStream)); + } } } URLConnection prjConnection = this.getURLConnection(WWIO.replaceSuffix(url.toString(), PROJECTION_FILE_SUFFIX)); - if (prjConnection != null) - { + if (prjConnection != null) { message = this.validateURLConnection(prjConnection, PROJECTION_CONTENT_TYPES); - if (message != null) + if (message != null) { Logging.logger().warning(message); - else - { + } else { InputStream prjStream = this.getURLStream(prjConnection); - if (prjStream != null) + if (prjStream != null) { this.prjChannel = Channels.newChannel(WWIO.getBufferedInputStream(prjStream)); + } } } @@ -737,34 +779,32 @@ protected void initializeFromURL(URL url, AVList params) throws IOException // Open the shapefile attribute source as a DBaseFile. We let the DBaseFile determine how to handle source URL. URL dbfURL = WWIO.makeURL(WWIO.replaceSuffix(url.toString(), ATTRIBUTE_FILE_SUFFIX)); - if (dbfURL != null) - { - try - { + if (dbfURL != null) { + try { this.attributeFile = new DBaseFile(dbfURL); - } - catch (Exception e) - { + } catch (Exception e) { // Exception already logged by DBaseFile constructor. } } } protected void initializeFromStreams(InputStream shpStream, InputStream shxStream, InputStream dbfStream, - InputStream prjStream, AVList params) throws IOException - { + InputStream prjStream, AVList params) throws IOException { // Create Channels for the collection of resources used by the Shapefile reader. We wrap each source InputStream // in a BufferedInputStream because this increases read performance, even when the stream is wrapped in an NIO // Channel. - if (shpStream != null) + if (shpStream != null) { this.shpChannel = Channels.newChannel(WWIO.getBufferedInputStream(shpStream)); + } - if (shxStream != null) + if (shxStream != null) { this.shxChannel = Channels.newChannel(WWIO.getBufferedInputStream(shxStream)); + } - if (prjStream != null) + if (prjStream != null) { this.prjChannel = Channels.newChannel(WWIO.getBufferedInputStream(prjStream)); + } // Initialize the Shapefile before opening its associated attributes file. This avoids opening the attributes // file if an exception is thrown while opening the Shapefile. @@ -772,31 +812,24 @@ protected void initializeFromStreams(InputStream shpStream, InputStream shxStrea // Open the shapefile attribute source as a DBaseFile. We let the DBaseFile determine how to handle its source // InputStream. - if (dbfStream != null) - { - try - { + if (dbfStream != null) { + try { this.attributeFile = new DBaseFile(dbfStream); - } - catch (Exception e) - { + } catch (Exception e) { // Exception already logged by DBaseFile constructor. } } } - protected void initializeFromPath(String path, AVList params) throws IOException - { + protected void initializeFromPath(String path, AVList params) throws IOException { File file = new File(path); - if (file.exists()) - { + if (file.exists()) { this.initializeFromFile(file, params); return; } URL url = WWIO.makeURL(path); - if (url != null) - { + if (url != null) { this.initializeFromURL(url, params); return; } @@ -807,34 +840,32 @@ protected void initializeFromPath(String path, AVList params) throws IOException } /** - * Prepares the Shapefile for reading. This reads the Shapefile's accompanying index and projection (if they're - * available), validates the Shapefile's coordinate system, and reads the Shapefile's header. + * Prepares the Shapefile for reading. This reads the Shapefile's + * accompanying index and projection (if they're available), validates the + * Shapefile's coordinate system, and reads the Shapefile's header. * - * @param params arameter list describing metadata about the Shapefile, such as its map projection, or null to - * specify no additional parameters. + * @param params arameter list describing metadata about the Shapefile, such + * as its map projection, or null to specify no additional parameters. * - * @throws IOException if an error occurs while reading the Shapefile's header. + * @throws IOException if an error occurs while reading the Shapefile's + * header. */ - protected void initialize(AVList params) throws IOException - { + protected void initialize(AVList params) throws IOException { // Attempt to read this Shapefile's projection resource, and set any projection parameters parsed from that // resource. If reading the projection resource fails, log the exception and continue. - try - { + try { AVList csParams = this.readCoordinateSystem(); - if (csParams != null) + if (csParams != null) { this.setValues(csParams); - } - catch (IOException e) - { + } + } catch (IOException e) { Logging.logger().log(Level.WARNING, - Logging.getMessage("SHP.ExceptionAttemptingToReadProjection", this.getStringValue(AVKey.DISPLAY_NAME)), e); + Logging.getMessage("SHP.ExceptionAttemptingToReadProjection", this.getStringValue(AVKey.DISPLAY_NAME)), e); } // Set the Shapefile's caller specified parameters. We do this after reading the projection parameters to give // the caller's parameters priority over the projection parameters. - if (params != null) - { + if (params != null) { this.setValues(params); } @@ -843,8 +874,7 @@ protected void initialize(AVList params) throws IOException // about what the coordinates represent. Throw a WWRuntimeException if the projection is either invalid or // unsupported. Subsequent attempts to query the Shapefile's header data or read its records cause an exception. String message = this.validateCoordinateSystem(this); - if (message != null) - { + if (message != null) { throw new WWRuntimeException(message); } @@ -852,14 +882,11 @@ protected void initialize(AVList params) throws IOException // continue. We read the index after reading any projection information and assigning the caller specified // parameters. This ensures that any coordinates in the header are converted according to the Shapefile's // coordinate system. - try - { + try { this.index = this.readIndex(); - } - catch (IOException e) - { + } catch (IOException e) { Logging.logger().log(Level.WARNING, - Logging.getMessage("SHP.ExceptionAttemptingToReadIndex", this.getStringValue(AVKey.DISPLAY_NAME)), e); + Logging.getMessage("SHP.ExceptionAttemptingToReadIndex", this.getStringValue(AVKey.DISPLAY_NAME)), e); } // Read this Shapefile's header and flag the Shapefile as open. We read the header after reading any projection @@ -872,67 +899,51 @@ protected void initialize(AVList params) throws IOException this.setNormalizePoints(this.header.normalizePoints); } - protected InputStream getFileStream(String path) - { - try - { + protected InputStream getFileStream(String path) { + try { return new FileInputStream(path); - } - catch (Exception e) - { + } catch (Exception e) { return null; } } - protected URLConnection getURLConnection(String urlString) - { - try - { + protected URLConnection getURLConnection(String urlString) { + try { URL url = new URL(urlString); return url.openConnection(); - } - catch (Exception e) - { + } catch (Exception e) { return null; } } - protected InputStream getURLStream(URLConnection connection) - { - try - { + protected InputStream getURLStream(URLConnection connection) { + try { return connection.getInputStream(); - } - catch (Exception e) - { + } catch (Exception e) { return null; } } - protected String validateURLConnection(URLConnection connection, String[] acceptedContentTypes) - { - try - { - if (connection instanceof HttpURLConnection && - ((HttpURLConnection) connection).getResponseCode() != HttpURLConnection.HTTP_OK) - { + protected String validateURLConnection(URLConnection connection, String[] acceptedContentTypes) { + try { + if (connection instanceof HttpURLConnection + && ((HttpURLConnection) connection).getResponseCode() != HttpURLConnection.HTTP_OK) { return Logging.getMessage("HTTP.ResponseCode", ((HttpURLConnection) connection).getResponseCode(), - connection.getURL()); + connection.getURL()); } - } - catch (Exception e) - { + } catch (Exception e) { return Logging.getMessage("URLRetriever.ErrorOpeningConnection", connection.getURL()); } String contentType = connection.getContentType(); - if (WWUtil.isEmpty(contentType)) + if (WWUtil.isEmpty(contentType)) { return null; + } - for (String type : acceptedContentTypes) - { - if (contentType.trim().toLowerCase().startsWith(type)) + for (String type : acceptedContentTypes) { + if (contentType.trim().toLowerCase().startsWith(type)) { return null; + } } // Return an exception if the content type does not match the expected type. @@ -942,29 +953,24 @@ protected String validateURLConnection(URLConnection connection, String[] accept //**************************************************************// //******************** Header ********************************// //**************************************************************// - /** - * Reads the {@link Header} from this Shapefile. This file is assumed to have a header. + * Reads the {@link Header} from this Shapefile. This file is assumed to + * have a header. * * @return a {@link Header} instance. * * @throws IOException if the header cannot be read for any reason. */ - protected Header readHeader() throws IOException - { + protected Header readHeader() throws IOException { ByteBuffer buffer; - if (this.mappedShpBuffer != null) - { + if (this.mappedShpBuffer != null) { buffer = this.mappedShpBuffer; - } - else - { + } else { buffer = ByteBuffer.allocate(HEADER_LENGTH); WWIO.readChannelToBuffer(this.shpChannel, buffer); } - if (buffer.remaining() < HEADER_LENGTH) - { + if (buffer.remaining() < HEADER_LENGTH) { // Let the caller catch and log the message. throw new WWRuntimeException(Logging.getMessage("generic.InvalidFileLength", buffer.remaining())); } @@ -973,10 +979,12 @@ protected Header readHeader() throws IOException } /** - * Reads a {@link Header} instance from the given {@link java.nio.ByteBuffer}; + * Reads a {@link Header} instance from the given + * {@link java.nio.ByteBuffer}; *

      - * The buffer current position is assumed to be set at the start of the header and will be set to the end of the - * header after this method has completed. + * The buffer current position is assumed to be set at the start of the + * header and will be set to the end of the header after this method has + * completed. * * @param buffer the Header @link java.nio.ByteBuffer} to read from. * @@ -984,20 +992,17 @@ protected Header readHeader() throws IOException * * @throws IOException if the header cannot be read for any reason. */ - protected Header readHeaderFromBuffer(ByteBuffer buffer) throws IOException - { + protected Header readHeaderFromBuffer(ByteBuffer buffer) throws IOException { Header header = null; // Save the buffer's current position. int pos = buffer.position(); - try - { + try { // Read file code - first 4 bytes, big endian buffer.order(ByteOrder.BIG_ENDIAN); int fileCode = buffer.getInt(); - if (fileCode != FILE_CODE) - { + if (fileCode != FILE_CODE) { // Let the caller catch and log the message. throw new WWUnrecognizedException(Logging.getMessage("SHP.UnrecognizedShapefile", fileCode)); } @@ -1018,8 +1023,7 @@ protected Header readHeaderFromBuffer(ByteBuffer buffer) throws IOException // Check whether the shape type is supported String shapeType = getShapeType(type); - if (shapeType == null) - { + if (shapeType == null) { // Let the caller catch and log the message. throw new WWRuntimeException(Logging.getMessage("SHP.UnsupportedShapeType", type)); } @@ -1031,9 +1035,7 @@ protected Header readHeaderFromBuffer(ByteBuffer buffer) throws IOException header.shapeType = shapeType; header.boundingRectangle = rect.coords; header.normalizePoints = rect.isNormalized; - } - finally - { + } finally { // Move to the end of the header. buffer.position(pos + HEADER_LENGTH); } @@ -1044,30 +1046,33 @@ protected Header readHeaderFromBuffer(ByteBuffer buffer) throws IOException //**************************************************************// //******************** Index *********************************// //**************************************************************// - /** - * Reads the Shapefile's accompanying index file and return the indices as an array of integers. Each array element - * represents the byte offset of the i'th record from the start of the Shapefile. This returns null if - * this Shapefile has no accompanying index file, if the index file is empty, or if the JVM cannot allocate enough - * memory to hold the index. + * Reads the Shapefile's accompanying index file and return the indices as + * an array of integers. Each array element represents the byte offset of + * the i'th record from the start of the Shapefile. This returns + * null if this Shapefile has no accompanying index file, if + * the index file is empty, or if the JVM cannot allocate enough memory to + * hold the index. * - * @return the Shapefile's record offset index, or null if the Shapefile has no accompanying index - * file, if the index file is empty, or if the index cannot be allocated. + * @return the Shapefile's record offset index, or null if the + * Shapefile has no accompanying index file, if the index file is empty, or + * if the index cannot be allocated. * * @throws IOException if an exception occurs during reading. */ - protected int[] readIndex() throws IOException - { + protected int[] readIndex() throws IOException { // The Shapefile index resource is optional. Return null if we don't have a stream to an index resource. - if (this.shxChannel == null) + if (this.shxChannel == null) { return null; + } ByteBuffer buffer = ByteBuffer.allocate(HEADER_LENGTH); WWIO.readChannelToBuffer(this.shxChannel, buffer); // Return null if the index is empty or is smaller than the minimum required size. - if (buffer.remaining() < HEADER_LENGTH) + if (buffer.remaining() < HEADER_LENGTH) { return null; + } Header indexHeader = this.readHeaderFromBuffer(buffer); int numRecords = (indexHeader.fileLength - HEADER_LENGTH) / 8; @@ -1075,17 +1080,14 @@ protected int[] readIndex() throws IOException int indexLength = 8 * numRecords; // 8 bytes per record. int[] array; - try - { + try { buffer = ByteBuffer.allocate(indexLength); array = new int[numElements]; - } - catch (OutOfMemoryError e) - { + } catch (OutOfMemoryError e) { // Log a warning that we could not allocate enough memory to hold the Shapefile index. Shapefile parsing // can continue without the optional index, so we catch the exception and return immediately. Logging.logger().log(Level.WARNING, - Logging.getMessage("SHP.OutOfMemoryAllocatingIndex", this.getStringValue(AVKey.DISPLAY_NAME)), e); + Logging.getMessage("SHP.OutOfMemoryAllocatingIndex", this.getStringValue(AVKey.DISPLAY_NAME)), e); return null; } @@ -1094,8 +1096,7 @@ protected int[] readIndex() throws IOException buffer.asIntBuffer().get(array); - for (int i = 0; i < numElements; i++) - { + for (int i = 0; i < numElements; i++) { array[i] *= 2; // Convert indices from 16-bit words to byte indices. } @@ -1105,102 +1106,98 @@ protected int[] readIndex() throws IOException //**************************************************************// //******************** Coordinate System *********************// //**************************************************************// - /** - * Reads the Shapefile's accompanying projection file as an OGC coordinate system encoded in well-known text format, - * and returns the coordinate system parameters. This returns null if this Shapefile has no - * accompanying projection file or if the projection file is empty. For details, see the OGC Coordinate Transform - * Service (CT) specification at http://www.opengeospatial.org/standards/ct. + * Reads the Shapefile's accompanying projection file as an OGC coordinate + * system encoded in well-known text format, and returns the coordinate + * system parameters. This returns null if this Shapefile has + * no accompanying projection file or if the projection file is empty. For + * details, see the OGC Coordinate Transform Service (CT) specification at + * http://www.opengeospatial.org/standards/ct. * - * @return coordinate system parameters parsed from the projection file, or null if this Shapefile has - * no accompanying projection file or the projection file is empty. + * @return coordinate system parameters parsed from the projection file, or + * null if this Shapefile has no accompanying projection file + * or the projection file is empty. * * @throws IOException if an exception occurs during reading. */ - protected AVList readCoordinateSystem() throws IOException - { + protected AVList readCoordinateSystem() throws IOException { // The Shapefile projection resource is optional. Return the parameter list unchanged if we don't have a stream // to a projection resource. - if (this.prjChannel == null) + if (this.prjChannel == null) { return null; + } // Read the Shapefile's associated projection to a String, using the default character encoding. Decode the // projection text as an OGC coordinate system formatted as well-known text. String text = WWIO.readChannelToString(this.prjChannel, null); // Return null if the projection file is empty. - if (WWUtil.isEmpty(text)) + if (WWUtil.isEmpty(text)) { return null; + } return WorldFile.decodeOGCCoordinateSystemWKT(text, null); } /** - * Returns a string indicating an error with the Shapefile's coordinate system parameters, or null to indicate that - * the coordinate parameters are valid. + * Returns a string indicating an error with the Shapefile's coordinate + * system parameters, or null to indicate that the coordinate parameters are + * valid. * * @param params the Shapefile's coordinate system parameters. * - * @return a non-empty string if the coordinate system parameters are invalid; null otherwise. + * @return a non-empty string if the coordinate system parameters are + * invalid; null otherwise. */ - protected String validateCoordinateSystem(AVList params) - { + protected String validateCoordinateSystem(AVList params) { Object o = params.getValue(AVKey.COORDINATE_SYSTEM); - if (!this.hasKey(AVKey.COORDINATE_SYSTEM)) - { + if (!this.hasKey(AVKey.COORDINATE_SYSTEM)) { Logging.logger().warning( - Logging.getMessage("generic.UnspecifiedCoordinateSystem", this.getStringValue(AVKey.DISPLAY_NAME))); + Logging.getMessage("generic.UnspecifiedCoordinateSystem", this.getStringValue(AVKey.DISPLAY_NAME))); return null; - } - else if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(o)) - { + } else if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(o)) { return null; - } - else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) - { + } else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) { return this.validateProjection(params); - } - else - { + } else { return Logging.getMessage("generic.UnsupportedCoordinateSystem", o); } } /** - * Returns a string indicating an error with the Shapefile's projection parameters, or null to indicate that the - * projection parameters are valid. + * Returns a string indicating an error with the Shapefile's projection + * parameters, or null to indicate that the projection parameters are valid. * * @param params the Shapefile's projection parameters. * - * @return a non-empty string if the projection parameters are invalid; null otherwise. + * @return a non-empty string if the projection parameters are invalid; null + * otherwise. */ - protected String validateProjection(AVList params) - { + protected String validateProjection(AVList params) { Object proj = params.getValue(AVKey.PROJECTION_NAME); - if (AVKey.PROJECTION_UTM.equals(proj)) - { + if (AVKey.PROJECTION_UTM.equals(proj)) { StringBuilder sb = new StringBuilder(); // Validate the UTM zone. Object o = params.getValue(AVKey.PROJECTION_ZONE); - if (o == null) + if (o == null) { sb.append(Logging.getMessage("generic.ZoneIsMissing")); - else if (!(o instanceof Integer) || ((Integer) o) < 1 || ((Integer) o) > 60) + } else if (!(o instanceof Integer) || ((Integer) o) < 1 || ((Integer) o) > 60) { sb.append(Logging.getMessage("generic.ZoneIsInvalid", o)); + } // Validate the UTM hemisphere. o = params.getValue(AVKey.PROJECTION_HEMISPHERE); - if (o == null) + if (o == null) { sb.append(sb.length() > 0 ? ", " : "").append(Logging.getMessage("generic.HemisphereIsMissing")); - else if (!o.equals(AVKey.NORTH) && !o.equals(AVKey.SOUTH)) + } else if (!o.equals(AVKey.NORTH) && !o.equals(AVKey.SOUTH)) { sb.append(sb.length() > 0 ? ", " : "").append(Logging.getMessage("generic.HemisphereIsInvalid", o)); + } return sb.length() > 0 ? sb.toString() : null; - } - else - { + } else { return Logging.getMessage("generic.UnsupportedProjection", proj); } } @@ -1208,21 +1205,18 @@ else if (!o.equals(AVKey.NORTH) && !o.equals(AVKey.SOUTH)) //**************************************************************// //******************** Shape Records *************************// //**************************************************************// - /** - * Reads the next {@link ShapefileRecord} instance from this Shapefile. This file is assumed to have one or more - * remaining records available. + * Reads the next {@link ShapefileRecord} instance from this Shapefile. This + * file is assumed to have one or more remaining records available. * * @return a {@link ShapefileRecord} instance. * * @throws IOException if the record cannot be read for any reason. */ - protected ShapefileRecord readNextRecord() throws IOException - { + protected ShapefileRecord readNextRecord() throws IOException { ByteBuffer buffer; - if (this.mappedShpBuffer != null) - { + if (this.mappedShpBuffer != null) { // Save the mapped buffer's current position and limit. int pos = this.mappedShpBuffer.position(); @@ -1239,12 +1233,11 @@ protected ShapefileRecord readNextRecord() throws IOException this.numBytesRead += recordLength; buffer = this.mappedShpBuffer; - } - else - { + } else { // Allocate a buffer to hold the record header. - if (this.recordHeaderBuffer == null) + if (this.recordHeaderBuffer == null) { this.recordHeaderBuffer = ByteBuffer.allocate(ShapefileRecord.RECORD_HEADER_LENGTH); + } // Read the header bytes. this.recordHeaderBuffer.clear(); @@ -1257,8 +1250,9 @@ protected ShapefileRecord readNextRecord() throws IOException int recordLength = ShapefileRecord.RECORD_HEADER_LENGTH + contentLength; // Allocate a buffer to hold the record content. - if (this.recordContentBuffer == null || this.recordContentBuffer.capacity() < recordLength) + if (this.recordContentBuffer == null || this.recordContentBuffer.capacity() < recordLength) { this.recordContentBuffer = ByteBuffer.allocate(recordLength); + } this.recordContentBuffer.limit(recordLength); this.recordContentBuffer.rewind(); @@ -1271,40 +1265,38 @@ protected ShapefileRecord readNextRecord() throws IOException } ShapefileRecord record; - try - { + try { record = this.readRecordFromBuffer(buffer); - } - finally - { + } finally { // Restore the mapped buffer's limit to its capacity. - if (this.mappedShpBuffer != null) + if (this.mappedShpBuffer != null) { this.mappedShpBuffer.limit(this.mappedShpBuffer.capacity()); + } } return record; } /** - * Reads a {@link ShapefileRecord} instance from the given {@link java.nio.ByteBuffer}, or null if the buffer - * contains a null record. + * Reads a {@link ShapefileRecord} instance from the given + * {@link java.nio.ByteBuffer}, or null if the buffer contains a null + * record. *

      - * The buffer current position is assumed to be set at the start of the record and will be set to the start of the - * next record after this method has completed. + * The buffer current position is assumed to be set at the start of the + * record and will be set to the start of the next record after this method + * has completed. * - * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read from. + * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read + * from. * * @return a {@link ShapefileRecord} instance. */ - protected ShapefileRecord readRecordFromBuffer(ByteBuffer buffer) - { + protected ShapefileRecord readRecordFromBuffer(ByteBuffer buffer) { ShapefileRecord record = this.createRecord(buffer); - if (record != null) - { + if (record != null) { // Read the record's attribute data. - if (this.attributeFile != null && this.attributeFile.hasNext()) - { + if (this.attributeFile != null && this.attributeFile.hasNext()) { record.setAttributes(this.attributeFile.nextRecord()); } } @@ -1313,48 +1305,47 @@ protected ShapefileRecord readRecordFromBuffer(ByteBuffer buffer) } /** - * Returns a new {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the specified - * buffer. The buffer's current position is assumed to be set at the start of the record and will be set to the - * start of the next record after this method has completed. + * Returns a new + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} + * from the specified buffer. The buffer's current position is assumed to be + * set at the start of the record and will be set to the start of the next + * record after this method has completed. *

      - * This returns an instance of of ShapefileRecord appropriate for the record's shape type. For example, if the - * record's shape type is SHAPE_POINT, this returns a ShapefileRecordPoint, and if the - * record's shape type is SHAPE_NULL, this returns ShapefileRecordNull. + * This returns an instance of of ShapefileRecord appropriate for the + * record's shape type. For example, if the record's shape type is + * SHAPE_POINT, this returns a + * ShapefileRecordPoint, and if the record's shape type is + * SHAPE_NULL, this returns ShapefileRecordNull. *

      - * This returns null if the record's shape type is not one of the following types: - * SHAPE_POINT, SHAPE_POINT_M, SHAPE_POINT_Z, SHAPE_MULTI_POINT, - * SHAPE_MULTI_POINT_M, SHAPE_MULTI_POINT_Z, SHAPE_NULL, - * SHAPE_POLYGON, SHAPE_POLYGON_M, SHAPE_POLYGON_Z, - * SHAPE_POLYLINE, SHAPE_POLYLINE_M, SHAPE_POLYLINE_Z. + * This returns null if the record's shape type is not one of + * the following types: SHAPE_POINT, + * SHAPE_POINT_M, SHAPE_POINT_Z, + * SHAPE_MULTI_POINT, SHAPE_MULTI_POINT_M, + * SHAPE_MULTI_POINT_Z, SHAPE_NULL, + * SHAPE_POLYGON, SHAPE_POLYGON_M, + * SHAPE_POLYGON_Z, SHAPE_POLYLINE, + * SHAPE_POLYLINE_M, SHAPE_POLYLINE_Z. * * @param buffer the buffer containing the record's content. * - * @return a new {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} instance, null if the - * record's shape type is not one of the recognized types. + * @return a new + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} instance, + * null if the record's shape type is not one of the recognized + * types. */ - protected ShapefileRecord createRecord(ByteBuffer buffer) - { + protected ShapefileRecord createRecord(ByteBuffer buffer) { String shapeType = this.readRecordShapeType(buffer); // Select proper record class - if (isPointType(shapeType)) - { + if (isPointType(shapeType)) { return this.createPoint(buffer); - } - else if (isMultiPointType(shapeType)) - { + } else if (isMultiPointType(shapeType)) { return this.createMultiPoint(buffer); - } - else if (isPolylineType(shapeType)) - { + } else if (isPolylineType(shapeType)) { return this.createPolyline(buffer); - } - else if (isPolygonType(shapeType)) - { + } else if (isPolygonType(shapeType)) { return this.createPolygon(buffer); - } - else if (isNullType(shapeType)) - { + } else if (isNullType(shapeType)) { return this.createNull(buffer); } @@ -1362,78 +1353,92 @@ else if (isNullType(shapeType)) } /** - * Returns a new "null" {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the specified buffer. + * Returns a new "null" + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the + * specified buffer. *

      - * The buffer current position is assumed to be set at the start of the record and will be set to the start of the - * next record after this method has completed. + * The buffer current position is assumed to be set at the start of the + * record and will be set to the start of the next record after this method + * has completed. * * @param buffer the buffer containing the point record's content. * - * @return a new point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. + * @return a new point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. */ - protected ShapefileRecord createNull(ByteBuffer buffer) - { + protected ShapefileRecord createNull(ByteBuffer buffer) { return new ShapefileRecordNull(this, buffer); } /** - * Returns a new point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the specified buffer. + * Returns a new point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the + * specified buffer. *

      - * The buffer current position is assumed to be set at the start of the record and will be set to the start of the - * next record after this method has completed. + * The buffer current position is assumed to be set at the start of the + * record and will be set to the start of the next record after this method + * has completed. * * @param buffer the buffer containing the point record's content. * - * @return a new point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. + * @return a new point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. */ - protected ShapefileRecord createPoint(ByteBuffer buffer) - { + protected ShapefileRecord createPoint(ByteBuffer buffer) { return new ShapefileRecordPoint(this, buffer); } /** - * Returns a new multi-point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the specified - * buffer. + * Returns a new multi-point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the + * specified buffer. *

      - * The buffer current position is assumed to be set at the start of the record and will be set to the start of the - * next record after this method has completed. + * The buffer current position is assumed to be set at the start of the + * record and will be set to the start of the next record after this method + * has completed. * * @param buffer the buffer containing the multi-point record's content. * - * @return a new point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. + * @return a new point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. */ - protected ShapefileRecord createMultiPoint(ByteBuffer buffer) - { + protected ShapefileRecord createMultiPoint(ByteBuffer buffer) { return new ShapefileRecordMultiPoint(this, buffer); } /** - * Returns a new polyline {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the specified buffer. + * Returns a new polyline + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the + * specified buffer. *

      - * The buffer current position is assumed to be set at the start of the record and will be set to the start of the - * next record after this method has completed. + * The buffer current position is assumed to be set at the start of the + * record and will be set to the start of the next record after this method + * has completed. * * @param buffer the buffer containing the polyline record's content. * - * @return a new point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. + * @return a new point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. */ - protected ShapefileRecord createPolyline(ByteBuffer buffer) - { + protected ShapefileRecord createPolyline(ByteBuffer buffer) { return new ShapefileRecordPolyline(this, buffer); } /** - * Returns a new polygon {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the specified buffer. + * Returns a new polygon + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord} from the + * specified buffer. *

      - * The buffer current position is assumed to be set at the start of the record and will be set to the start of the - * next record after this method has completed. + * The buffer current position is assumed to be set at the start of the + * record and will be set to the start of the next record after this method + * has completed. * * @param buffer the buffer containing the polygon record's content. * - * @return a new point {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. + * @return a new point + * {@link gov.nasa.worldwind.formats.shapefile.ShapefileRecord}. */ - protected ShapefileRecord createPolygon(ByteBuffer buffer) - { + protected ShapefileRecord createPolygon(ByteBuffer buffer) { return new ShapefileRecordPolygon(this, buffer); } @@ -1444,16 +1449,14 @@ protected ShapefileRecord createPolygon(ByteBuffer buffer) * * @return the record's shape type. */ - protected String readRecordShapeType(ByteBuffer buffer) - { + protected String readRecordShapeType(ByteBuffer buffer) { // Read shape type - little endian buffer.order(ByteOrder.LITTLE_ENDIAN); int type = buffer.getInt(buffer.position() + 2 * 4); // skip record number and length as ints String shapeType = this.getShapeType(type); - if (shapeType == null) - { + if (shapeType == null) { // Let the caller catch and log the exception. throw new WWRuntimeException(Logging.getMessage("SHP.UnsupportedShapeType", type)); } @@ -1462,17 +1465,16 @@ protected String readRecordShapeType(ByteBuffer buffer) } /** - * Maps the integer shape type from the shapefile to the corresponding shape type defined above. + * Maps the integer shape type from the shapefile to the corresponding shape + * type defined above. * * @param type the integer shape type. * * @return the mapped shape type. */ - protected String getShapeType(int type) - { + protected String getShapeType(int type) { // Cases commented out indicate shape types not implemented - switch (type) - { + switch (type) { case 0: return SHAPE_NULL; case 1: @@ -1504,7 +1506,6 @@ protected String getShapeType(int type) // case 31: // return SHAPE_MULTI_PATCH; - default: return null; // unsupported shape type } @@ -1513,45 +1514,41 @@ protected String getShapeType(int type) //**************************************************************// //******************** Point Data ****************************// //**************************************************************// - /** - * Add point coordinates to the Shapefile starting at the buffer's positions and ending at the specified number of - * points, and returns an address to the point coordinates in the Shapefile's backing point buffer. Points are read - * as (X,Y) pairs of 64-bit floating point numbers. This throws an exception if the JVM cannot allocate enough - * memory to hold the Shapefile's backing point buffer. - * - * @param record the record associated with the point coordinates, may be null. - * @param buffer the buffer to read points from. + * Add point coordinates to the Shapefile starting at the buffer's positions + * and ending at the specified number of points, and returns an address to + * the point coordinates in the Shapefile's backing point buffer. Points are + * read as (X,Y) pairs of 64-bit floating point numbers. This throws an + * exception if the JVM cannot allocate enough memory to hold the + * Shapefile's backing point buffer. + * + * @param record the record associated with the point coordinates, may be + * null. + * @param buffer the buffer to read points from. * @param numPoints the number of (X,Y) pairs to read. * * @return the point's address in the Shapefile's backing point buffer. */ - protected int addPoints(ShapefileRecord record, ByteBuffer buffer, int numPoints) - { + protected int addPoints(ShapefileRecord record, ByteBuffer buffer, int numPoints) { DoubleBuffer pointBuffer; // Read the point data, keeping track of the start and end of the point data. int pos = buffer.position(); int limit = buffer.position() + 2 * WWBufferUtil.SIZEOF_DOUBLE * numPoints; - try - { + try { // Set the buffer's limit to include the number of bytes required to hold 2 double precision values for each // point, then read the point data between the buffer's current position and limit. buffer.limit(limit); pointBuffer = this.readPoints(record, buffer); - } - finally - { + } finally { // Restore the buffer's limit to its original value, and set its position at the end of the point data. buffer.clear(); buffer.position(limit); } // Add the point data to the Shapefile's internal point buffer. - if (this.mappedShpBuffer != null) - { - if (this.pointBuffer == null) - { + if (this.mappedShpBuffer != null) { + if (this.pointBuffer == null) { // Create a VecBufferBlocks to hold this Shapefile's point data. Shapefile points are 2-tuples stored in // IEEE 64-bit floating point format, in little endian byte order. ByteBuffer buf = this.mappedShpBuffer.duplicate(); @@ -1562,29 +1559,23 @@ protected int addPoints(ShapefileRecord record, ByteBuffer buffer, int numPoints // Add the point's byte range to the VecBufferBlocks. return ((VecBufferBlocks) this.pointBuffer).addBlock(pos, limit - 1); - } - else - { - if (this.pointBuffer == null) - { + } else { + if (this.pointBuffer == null) { // Create a CompoundVecBuffer to hold this Shapefile's point data. int totalPointsEstimate = this.computeNumberOfPointsEstimate(); DoubleBuffer doubleBuffer; - try - { + try { doubleBuffer = Buffers.newDirectDoubleBuffer(2 * totalPointsEstimate); - } - catch (OutOfMemoryError e) - { + } catch (OutOfMemoryError e) { // Let the caller catch and log the exception. If we cannot allocate enough memory to hold the // point buffer, we throw an exception indicating that the read operation should be terminated. throw new WWRuntimeException(Logging.getMessage("SHP.OutOfMemoryAllocatingPointBuffer", - this.getStringValue(AVKey.DISPLAY_NAME)), e); + this.getStringValue(AVKey.DISPLAY_NAME)), e); } this.pointBuffer = new VecBufferSequence( - new VecBuffer(2, new BufferWrapper.DoubleBufferWrapper(doubleBuffer))); + new VecBuffer(2, new BufferWrapper.DoubleBufferWrapper(doubleBuffer))); } // Append the point coordinates to the VecBufferSequence. @@ -1599,8 +1590,7 @@ protected int addPoints(ShapefileRecord record, ByteBuffer buffer, int numPoints * @return a liberal estimate of the number of points in the shapefile. */ @SuppressWarnings({"StringEquality"}) - protected int computeNumberOfPointsEstimate() - { + protected int computeNumberOfPointsEstimate() { // Compute the header overhead, subtract it from the file size, then divide by point size to get the estimate. // The Parts array is not included in the overhead, so the estimate will be slightly greater than the number of // points needed if the shape is a type with a Parts array. Measure values and ranges are also not included in @@ -1610,75 +1600,77 @@ protected int computeNumberOfPointsEstimate() final int numRecords = this.getNumberOfRecords(); // Return very liberal estimate based on file size if num records unknown. - if (numRecords < 0) + if (numRecords < 0) { return (this.getLength() - HEADER_LENGTH) / 16; // num X, Y tuples that can fit in the file length - + } int overhead = HEADER_LENGTH + numRecords * 12; //12 bytes per record for record header and record shape type String shapeType = this.getShapeType(); - if (shapeType == SHAPE_POINT || shapeType == SHAPE_POINT_M) + if (shapeType == SHAPE_POINT || shapeType == SHAPE_POINT_M) { return (this.getLength() - overhead) / 16; // 16 = two doubles, X and Y - - if (shapeType == SHAPE_MULTI_POINT || shapeType == SHAPE_MULTI_POINT_M) - // Add 32 bytes per record for bounding box + 4 bytes for one int per record + } + if (shapeType == SHAPE_MULTI_POINT || shapeType == SHAPE_MULTI_POINT_M) // Add 32 bytes per record for bounding box + 4 bytes for one int per record + { return (this.getLength() - (overhead + numRecords * (32 + 4))) / 16; // 16 = two doubles, X and Y - + } if (shapeType == SHAPE_POLYLINE || shapeType == SHAPE_POLYGON - || shapeType == SHAPE_POLYLINE_M || shapeType == SHAPE_POLYGON_M) - // Add 32 bytes per record for bounding box + 8 bytes for two ints per record + || shapeType == SHAPE_POLYLINE_M || shapeType == SHAPE_POLYGON_M) // Add 32 bytes per record for bounding box + 8 bytes for two ints per record + { return (this.getLength() - (overhead + numRecords * (32 + 8))) / 16; // 16 = two doubles, X and Y - - if (shapeType == SHAPE_POINT_Z) + } + if (shapeType == SHAPE_POINT_Z) { return (this.getLength() - overhead) / 24; // 24 = three doubles, X, Y, Z - - if (shapeType == SHAPE_MULTI_POINT_Z) - // Add 48 bytes per record for bounding box + 4 bytes for one int per record + } + if (shapeType == SHAPE_MULTI_POINT_Z) // Add 48 bytes per record for bounding box + 4 bytes for one int per record + { return (this.getLength() - (overhead + numRecords * (48 + 4))) / 24; // 24 = three doubles, X, Y, Z - - if (shapeType == SHAPE_POLYLINE_Z || shapeType == SHAPE_POLYGON_Z) - // Add 48 bytes per record for bounding box + 8 bytes for two ints per record + } + if (shapeType == SHAPE_POLYLINE_Z || shapeType == SHAPE_POLYGON_Z) // Add 48 bytes per record for bounding box + 8 bytes for two ints per record + { return (this.getLength() - (overhead + numRecords * (48 + 8))) / 24; // 24 = three doubles, X, Y and Z - + } // The shape type should have been checked before calling this method, so we shouldn't reach this code. // Let the caller catch and log the exception. throw new WWRuntimeException(Logging.getMessage("SHP.UnsupportedShapeType", shapeType)); } /** - * Returns a {@link java.nio.DoubleBuffer} containing the (X,Y) tuples between the buffer's position and its limit. - * This returns null if the buffer is null or if the buffer has no remaining elements. The returned coordinates are - * interpreted according to the Shapefile's coordinate system. This throws a {@link - * gov.nasa.worldwind.exception.WWRuntimeException} if the coordinate system is unsupported. + * Returns a {@link java.nio.DoubleBuffer} containing the (X,Y) tuples + * between the buffer's position and its limit. This returns null if the + * buffer is null or if the buffer has no remaining elements. The returned + * coordinates are interpreted according to the Shapefile's coordinate + * system. This throws a {@link + * gov.nasa.worldwind.exception.WWRuntimeException} if the coordinate system + * is unsupported. *

      - * The buffer current position is assumed to be set at the start of the point data and will be set to the end of the - * point data after this method has completed. + * The buffer current position is assumed to be set at the start of the + * point data and will be set to the end of the point data after this method + * has completed. * - * @param record the record associated with the point coordinates, may be null. + * @param record the record associated with the point coordinates, may be + * null. * @param buffer the buffer to read point coordinates from. * * @return a buffer containing the point coordinates. * - * @throws WWRuntimeException if the Shapefile's coordinate system is unsupported. + * @throws WWRuntimeException if the Shapefile's coordinate system is + * unsupported. */ - protected DoubleBuffer readPoints(ShapefileRecord record, ByteBuffer buffer) - { - if (buffer == null || !buffer.hasRemaining()) + protected DoubleBuffer readPoints(ShapefileRecord record, ByteBuffer buffer) { + if (buffer == null || !buffer.hasRemaining()) { return null; + } Object o = this.getValue(AVKey.COORDINATE_SYSTEM); - if (!this.hasKey(AVKey.COORDINATE_SYSTEM)) + if (!this.hasKey(AVKey.COORDINATE_SYSTEM)) { return this.readUnspecifiedPoints(record, buffer); - - else if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(o)) + } else if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(o)) { return this.readGeographicPoints(record, buffer); - - else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) + } else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) { return this.readProjectedPoints(record, buffer); - - else - { + } else { // The Shapefile's coordinate system is unsupported. This should never happen because the coordinate system // is validated during initialization, but we check anyway. Let the caller catch and log the message. throw new WWRuntimeException(Logging.getMessage("generic.UnsupportedCoordinateSystem", o)); @@ -1686,39 +1678,41 @@ else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) } /** - * Returns a {@link java.nio.DoubleBuffer} containing the (X,Y) tuples between the buffer's position and its limit. - * The coordinates are assumed to be in an unspecified coordinate system and are not changed. + * Returns a {@link java.nio.DoubleBuffer} containing the (X,Y) tuples + * between the buffer's position and its limit. The coordinates are assumed + * to be in an unspecified coordinate system and are not changed. * - * @param record the record associated with the point coordinates, may be null. + * @param record the record associated with the point coordinates, may be + * null. * @param buffer the buffer to read point coordinates from. * * @return a buffer containing the point coordinates. */ @SuppressWarnings({"UnusedDeclaration"}) - protected DoubleBuffer readUnspecifiedPoints(ShapefileRecord record, ByteBuffer buffer) - { + protected DoubleBuffer readUnspecifiedPoints(ShapefileRecord record, ByteBuffer buffer) { // Create a view of the buffer as a doubles. return buffer.asDoubleBuffer(); } /** - * Returns a {@link java.nio.DoubleBuffer} containing the geographic (longitude, latitude) tuples between the - * buffer's position and its limit. This normalizes the geographic coordinates to the range +-90 latitude and +-180 - * longitude if the record is non-null and {@link ShapefileRecord#isNormalizePoints()} returns true. - * - * @param record the record associated with the point coordinates, may be null. + * Returns a {@link java.nio.DoubleBuffer} containing the geographic + * (longitude, latitude) tuples between the buffer's position and its limit. + * This normalizes the geographic coordinates to the range +-90 latitude and + * +-180 longitude if the record is non-null and + * {@link ShapefileRecord#isNormalizePoints()} returns true. + * + * @param record the record associated with the point coordinates, may be + * null. * @param buffer the buffer to read point coordinates from. * * @return a buffer containing the geographic point coordinates. */ - protected DoubleBuffer readGeographicPoints(ShapefileRecord record, ByteBuffer buffer) - { + protected DoubleBuffer readGeographicPoints(ShapefileRecord record, ByteBuffer buffer) { // Create a view of the buffer as a doubles. DoubleBuffer doubleBuffer = buffer.asDoubleBuffer(); // Normalize the buffer of geographic point coordinates if the record is flagged as needing normalization. - if (record != null && record.isNormalizePoints()) - { + if (record != null && record.isNormalizePoints()) { WWUtil.normalizeGeographicCoordinates(doubleBuffer); doubleBuffer.rewind(); } @@ -1727,25 +1721,27 @@ protected DoubleBuffer readGeographicPoints(ShapefileRecord record, ByteBuffer b } /** - * Returns a {@link java.nio.DoubleBuffer} containing the projected (X,Y) tuples between the buffer's position and - * its limit, converted to geographic coordinates (latitude,longitude). The returned coordinates are interpreted - * according to the Shapefile's projection. This throws a {@link gov.nasa.worldwind.exception.WWRuntimeException} if - * the projection is unsupported. - * - * @param record the record associated with the point coordinates, may be null. + * Returns a {@link java.nio.DoubleBuffer} containing the projected (X,Y) + * tuples between the buffer's position and its limit, converted to + * geographic coordinates (latitude,longitude). The returned coordinates are + * interpreted according to the Shapefile's projection. This throws a + * {@link gov.nasa.worldwind.exception.WWRuntimeException} if the projection + * is unsupported. + * + * @param record the record associated with the point coordinates, may be + * null. * @param buffer the buffer to read point coordinates from. * - * @return a buffer containing geographic point coordinates converted form projected coordinates. + * @return a buffer containing geographic point coordinates converted form + * projected coordinates. * * @throws WWRuntimeException if the Shapefile's projection is unsupported. */ @SuppressWarnings({"UnusedDeclaration"}) - protected DoubleBuffer readProjectedPoints(ShapefileRecord record, ByteBuffer buffer) - { + protected DoubleBuffer readProjectedPoints(ShapefileRecord record, ByteBuffer buffer) { Object o = this.getValue(AVKey.PROJECTION_NAME); - if (AVKey.PROJECTION_UTM.equals(o)) - { + if (AVKey.PROJECTION_UTM.equals(o)) { // The Shapefile's coordinate system is UTM. Convert the UTM coordinates to geographic. The zone and hemisphere // parameters have already been validated in validateBounds. Integer zone = (Integer) this.getValue(AVKey.PROJECTION_ZONE); @@ -1757,9 +1753,7 @@ protected DoubleBuffer readProjectedPoints(ShapefileRecord record, ByteBuffer bu doubleBuffer.rewind(); return doubleBuffer; - } - else - { + } else { // The Shapefile's coordinate system projection is unsupported. This should never happen because the // projection is validated during initialization, but we check anyway. Let the caller catch and log the // message. @@ -1770,47 +1764,50 @@ protected DoubleBuffer readProjectedPoints(ShapefileRecord record, ByteBuffer bu //**************************************************************// //******************** Bounding Rectangle ********************// //**************************************************************// - /** - * Stores a bounding rectangle's coordinates, and if the coordinates are normalized. If isNormalized is - * true, this indicates that the original coordinate values are out of range and required - * normalization. The shapefile and shapefile records use this to determine which records must have their point - * coordinates normalized. Normalization is rarely needed, and this enables the shapefile to normalize only point - * coordinates associated with records that require it. + * Stores a bounding rectangle's coordinates, and if the coordinates are + * normalized. If isNormalized is true, this + * indicates that the original coordinate values are out of range and + * required normalization. The shapefile and shapefile records use this to + * determine which records must have their point coordinates normalized. + * Normalization is rarely needed, and this enables the shapefile to + * normalize only point coordinates associated with records that require it. */ - protected static class BoundingRectangle - { - /** Four-element array of the bounding rectangle's coordinates, ordered as follows: (minY, maxY, minX, maxX). */ + protected static class BoundingRectangle { + + /** + * Four-element array of the bounding rectangle's coordinates, ordered + * as follows: (minY, maxY, minX, maxX). + */ public double[] coords; - /** True if the coordinates are normalized, and false otherwise. */ + /** + * True if the coordinates are normalized, and false otherwise. + */ public boolean isNormalized; } /** - * Returns a bounding rectangle from the specified buffer. This reads four doubles and interprets them as a bounding - * rectangle in the following order: (minX, minY, maxX, maxY). The returned rectangle's coordinates are interpreted - * according to the Shapefile's coordinate system. This throws a {@link gov.nasa.worldwind.exception.WWRuntimeException} - * if the coordinate system is unsupported. + * Returns a bounding rectangle from the specified buffer. This reads four + * doubles and interprets them as a bounding rectangle in the following + * order: (minX, minY, maxX, maxY). The returned rectangle's coordinates are + * interpreted according to the Shapefile's coordinate system. This throws a + * {@link gov.nasa.worldwind.exception.WWRuntimeException} if the coordinate + * system is unsupported. * * @param buffer the buffer to read from. * * @return a bounding rectangle with coordinates from the specified buffer. */ - protected BoundingRectangle readBoundingRectangle(ByteBuffer buffer) - { + protected BoundingRectangle readBoundingRectangle(ByteBuffer buffer) { Object o = this.getValue(AVKey.COORDINATE_SYSTEM); - if (!this.hasKey(AVKey.COORDINATE_SYSTEM)) + if (!this.hasKey(AVKey.COORDINATE_SYSTEM)) { return this.readUnspecifiedBoundingRectangle(buffer); - - else if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(o)) + } else if (AVKey.COORDINATE_SYSTEM_GEOGRAPHIC.equals(o)) { return this.readGeographicBoundingRectangle(buffer); - - else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) + } else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) { return this.readProjectedBoundingRectangle(buffer); - - else - { + } else { // The Shapefile's coordinate system is unsupported. This should never happen because the coordinate system // is validated during initialization, but we check anyway. Let the caller catch and log the message. throw new WWRuntimeException(Logging.getMessage("generic.UnsupportedCoordinateSystem", o)); @@ -1818,17 +1815,18 @@ else if (AVKey.COORDINATE_SYSTEM_PROJECTED.equals(o)) } /** - * Returns a bounding rectangle from the specified buffer. This reads four doubles and interprets them as a bounding - * rectangle in the following order: (minX, minY, maxX, maxY). The coordinates are assumed to be in an unspecified - * coordinate system and are not changed. + * Returns a bounding rectangle from the specified buffer. This reads four + * doubles and interprets them as a bounding rectangle in the following + * order: (minX, minY, maxX, maxY). The coordinates are assumed to be in an + * unspecified coordinate system and are not changed. * * @param buffer the buffer to read bounding rectangle coordinates from. * - * @return a bounding rectangle with coordinates from the specified buffer. The rectangle's coordinates are ordered - * as follows: (minY, maxY, minX, maxX). + * @return a bounding rectangle with coordinates from the specified buffer. + * The rectangle's coordinates are ordered as follows: (minY, maxY, minX, + * maxX). */ - protected BoundingRectangle readUnspecifiedBoundingRectangle(ByteBuffer buffer) - { + protected BoundingRectangle readUnspecifiedBoundingRectangle(ByteBuffer buffer) { // Read the bounding rectangle coordinates in the following order: minY, maxY, minX, maxX. BoundingRectangle rect = new BoundingRectangle(); rect.coords = this.readBoundingRectangleCoordinates(buffer); @@ -1836,53 +1834,54 @@ protected BoundingRectangle readUnspecifiedBoundingRectangle(ByteBuffer buffer) } /** - * Returns a bounding rectangle from the specified buffer. This reads four doubles and interprets them as a - * Geographic bounding rectangle in the following order: (minLat, maxLat, minLon, maxLon). If any of the coordinates - * are out of the range -90/+90 latitude and -180/+180 longitude, this normalizes the coordinates and sets the - * rectangle's {@link gov.nasa.worldwind.formats.shapefile.Shapefile.BoundingRectangle#isNormalized} property to - * true. + * Returns a bounding rectangle from the specified buffer. This reads four + * doubles and interprets them as a Geographic bounding rectangle in the + * following order: (minLat, maxLat, minLon, maxLon). If any of the + * coordinates are out of the range -90/+90 latitude and -180/+180 + * longitude, this normalizes the coordinates and sets the rectangle's + * {@link gov.nasa.worldwind.formats.shapefile.Shapefile.BoundingRectangle#isNormalized} + * property to true. * * @param buffer the buffer to read bounding rectangle coordinates from. * - * @return a bounding rectangle with coordinates from the specified buffer. The rectangle's coordinates are ordered - * as follows: (minLat, maxLat, minLon, maxLon). + * @return a bounding rectangle with coordinates from the specified buffer. + * The rectangle's coordinates are ordered as follows: (minLat, maxLat, + * minLon, maxLon). */ - protected BoundingRectangle readGeographicBoundingRectangle(ByteBuffer buffer) - { + protected BoundingRectangle readGeographicBoundingRectangle(ByteBuffer buffer) { // Read the bounding rectangle coordinates in the following order: minLat, maxLat, minLon, maxLon. BoundingRectangle rect = new BoundingRectangle(); rect.coords = this.readBoundingRectangleCoordinates(buffer); // The bounding rectangle's min latitude exceeds -90. Set the min latitude to -90. Correct the max latitude if // the normalized min latitude is greater than the max latitude. - if (rect.coords[0] < -90) - { + if (rect.coords[0] < -90) { double normalizedLat = Angle.normalizedLatitude(Angle.fromDegrees(rect.coords[0])).degrees; rect.coords[0] = -90; rect.isNormalized = true; - if (rect.coords[1] < normalizedLat) + if (rect.coords[1] < normalizedLat) { rect.coords[1] = normalizedLat; + } } // The bounding rectangle's max latitude exceeds +90. Set the max latitude to +90. Correct the min latitude if // the normalized max latitude is less than the min latitude. - if (rect.coords[1] > 90) - { + if (rect.coords[1] > 90) { double normalizedLat = Angle.normalizedLatitude(Angle.fromDegrees(rect.coords[1])).degrees; rect.coords[1] = 90; rect.isNormalized = true; - if (rect.coords[0] > normalizedLat) + if (rect.coords[0] > normalizedLat) { rect.coords[0] = normalizedLat; + } } // The bounding rectangle's longitudes exceed +-180, therefore the rectangle spans the international // dateline. Set the longitude bound to (-180, 180) to contain the dateline spanning rectangle. - if (rect.coords[2] < -180 || rect.coords[3] > 180) - { + if (rect.coords[2] < -180 || rect.coords[3] > 180) { rect.coords[2] = -180; rect.coords[3] = 180; rect.isNormalized = true; @@ -1892,25 +1891,27 @@ protected BoundingRectangle readGeographicBoundingRectangle(ByteBuffer buffer) } /** - * Returns a bounding rectangle from the specified buffer. This reads four doubles and interprets them as a - * projected bounding rectangle in the following order: (minX, maxX, minY, maxY). The projected rectangle is - * converted to geographic coordinates before the rectangle is returned. The returned coordinates are interpreted - * according to the Shapefile's projection. This throws a {@link gov.nasa.worldwind.exception.WWRuntimeException} if - * the projection is unsupported. + * Returns a bounding rectangle from the specified buffer. This reads four + * doubles and interprets them as a projected bounding rectangle in the + * following order: (minX, maxX, minY, maxY). The projected rectangle is + * converted to geographic coordinates before the rectangle is returned. The + * returned coordinates are interpreted according to the Shapefile's + * projection. This throws a + * {@link gov.nasa.worldwind.exception.WWRuntimeException} if the projection + * is unsupported. * * @param buffer the buffer to read bounding rectangle coordinates from. * - * @return a bounding rectangle with coordinates from the specified buffer. The rectangle's coordinates are ordered - * as follows: (minLat, maxLat, minLon, maxLon). + * @return a bounding rectangle with coordinates from the specified buffer. + * The rectangle's coordinates are ordered as follows: (minLat, maxLat, + * minLon, maxLon). * * @throws WWRuntimeException if the Shapefile's projection is unsupported. */ - protected BoundingRectangle readProjectedBoundingRectangle(ByteBuffer buffer) - { + protected BoundingRectangle readProjectedBoundingRectangle(ByteBuffer buffer) { Object o = this.getValue(AVKey.PROJECTION_NAME); - if (AVKey.PROJECTION_UTM.equals(o)) - { + if (AVKey.PROJECTION_UTM.equals(o)) { // Read the bounding rectangle coordinates in the following order: minEast, minNorth, maxEast, maxNorth. double[] coords = ShapefileUtils.readDoubleArray(buffer, 4); // Convert the UTM bounding rectangle to a geographic bounding rectangle. The zone and hemisphere parameters @@ -1922,9 +1923,7 @@ protected BoundingRectangle readProjectedBoundingRectangle(ByteBuffer buffer) BoundingRectangle rect = new BoundingRectangle(); rect.coords = sector.toArrayDegrees(); return rect; - } - else - { + } else { // The Shapefile's coordinate system projection is unsupported. This should never happen because the // projection is validated during initialization, but we check anyway. Let the caller catch and log the // message. @@ -1933,16 +1932,18 @@ protected BoundingRectangle readProjectedBoundingRectangle(ByteBuffer buffer) } /** - * Reads a Shapefile bounding rectangle from the specified buffer. This reads four doubles and returns them as a - * four-element array in the following order: (minY, maxY, minX, maxX). This ordering is consistent with the - * ordering expected by {@link gov.nasa.worldwind.geom.Sector#fromDegrees(double[])}. + * Reads a Shapefile bounding rectangle from the specified buffer. This + * reads four doubles and returns them as a four-element array in the + * following order: (minY, maxY, minX, maxX). This ordering is consistent + * with the ordering expected by + * {@link gov.nasa.worldwind.geom.Sector#fromDegrees(double[])}. * * @param buffer the buffer to read from. * - * @return a four-element array ordered as follows: (minY, maxY, minX, maxX). + * @return a four-element array ordered as follows: (minY, maxY, minX, + * maxX). */ - protected double[] readBoundingRectangleCoordinates(ByteBuffer buffer) - { + protected double[] readBoundingRectangleCoordinates(ByteBuffer buffer) { // Read the bounding rectangle coordinates in the following order: minX, minY, maxX, maxY. double minx = buffer.getDouble(); double miny = buffer.getDouble(); @@ -1950,15 +1951,15 @@ protected double[] readBoundingRectangleCoordinates(ByteBuffer buffer) double maxy = buffer.getDouble(); // Return an array with bounding rectangle coordinates in the following order: minY, maxY, minX, maxX. - return new double[] {miny, maxy, minx, maxx}; + return new double[]{miny, maxy, minx, maxx}; } //**************************************************************// //******************** Static Utilities **********************// //**************************************************************// - /** - * Indicates whether a specified shape type may contain optional measure values. + * Indicates whether a specified shape type may contain optional measure + * values. * * @param shapeType the shape type to analyze. * @@ -1966,10 +1967,8 @@ protected double[] readBoundingRectangleCoordinates(ByteBuffer buffer) * * @throws IllegalArgumentException if shapeType is null. */ - public static boolean isMeasureType(String shapeType) - { - if (shapeType == null) - { + public static boolean isMeasureType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -1987,10 +1986,8 @@ public static boolean isMeasureType(String shapeType) * * @throws IllegalArgumentException if shapeType is null. */ - public static boolean isZType(String shapeType) - { - if (shapeType == null) - { + public static boolean isZType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -2008,10 +2005,8 @@ public static boolean isZType(String shapeType) * * @throws IllegalArgumentException if shapeType is null. */ - public static boolean isNullType(String shapeType) - { - if (shapeType == null) - { + public static boolean isNullType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -2021,7 +2016,8 @@ public static boolean isNullType(String shapeType) } /** - * Indicates whether a specified shape type is either {@link #SHAPE_POINT}, {@link #SHAPE_POINT_M} or {@link + * Indicates whether a specified shape type is either + * {@link #SHAPE_POINT}, {@link #SHAPE_POINT_M} or {@link * #SHAPE_POINT_Z}. * * @param shapeType the shape type to analyze. @@ -2030,21 +2026,20 @@ public static boolean isNullType(String shapeType) * * @throws IllegalArgumentException if shapeType is null. */ - public static boolean isPointType(String shapeType) - { - if (shapeType == null) - { + public static boolean isPointType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return shapeType.equals(Shapefile.SHAPE_POINT) || shapeType.equals(Shapefile.SHAPE_POINT_Z) - || shapeType.equals(Shapefile.SHAPE_POINT_M); + || shapeType.equals(Shapefile.SHAPE_POINT_M); } /** - * Indicates whether a specified shape type is either {@link #SHAPE_MULTI_POINT}, {@link #SHAPE_MULTI_POINT_M} or + * Indicates whether a specified shape type is either + * {@link #SHAPE_MULTI_POINT}, {@link #SHAPE_MULTI_POINT_M} or * {@link #SHAPE_MULTI_POINT_Z}. * * @param shapeType the shape type to analyze. @@ -2053,21 +2048,20 @@ public static boolean isPointType(String shapeType) * * @throws IllegalArgumentException if shapeType is null. */ - public static boolean isMultiPointType(String shapeType) - { - if (shapeType == null) - { + public static boolean isMultiPointType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return shapeType.equals(Shapefile.SHAPE_MULTI_POINT) || shapeType.equals(Shapefile.SHAPE_MULTI_POINT_Z) - || shapeType.equals(Shapefile.SHAPE_MULTI_POINT_M); + || shapeType.equals(Shapefile.SHAPE_MULTI_POINT_M); } /** - * Indicates whether a specified shape type is either {@link #SHAPE_POLYLINE}, {@link #SHAPE_POLYLINE_M} or {@link + * Indicates whether a specified shape type is either + * {@link #SHAPE_POLYLINE}, {@link #SHAPE_POLYLINE_M} or {@link * #SHAPE_POLYLINE_Z}. * * @param shapeType the shape type to analyze. @@ -2076,130 +2070,112 @@ public static boolean isMultiPointType(String shapeType) * * @throws IllegalArgumentException if shapeType is null. */ - public static boolean isPolylineType(String shapeType) - { - if (shapeType == null) - { + public static boolean isPolylineType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return shapeType.equals(Shapefile.SHAPE_POLYLINE) || shapeType.equals(Shapefile.SHAPE_POLYLINE_Z) - || shapeType.equals(Shapefile.SHAPE_POLYLINE_M); + || shapeType.equals(Shapefile.SHAPE_POLYLINE_M); } /** - * Indicates whether a specified shape type is either {@link #SHAPE_POLYGON}, {@link #SHAPE_POLYGON_M} or {@link + * Indicates whether a specified shape type is either + * {@link #SHAPE_POLYGON}, {@link #SHAPE_POLYGON_M} or {@link * #SHAPE_POLYGON_Z}. * * @param shapeType the shape type to analyze. * * @return true if the shape type is a polygon type. */ - public static boolean isPolygonType(String shapeType) - { - if (shapeType == null) - { + public static boolean isPolygonType(String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } return shapeType.equals(Shapefile.SHAPE_POLYGON) || shapeType.equals(Shapefile.SHAPE_POLYGON_Z) - || shapeType.equals(Shapefile.SHAPE_POLYGON_M); + || shapeType.equals(Shapefile.SHAPE_POLYGON_M); } - public String isExportFormatSupported(String mimeType) - { - if (KMLConstants.KML_MIME_TYPE.equalsIgnoreCase(mimeType)) + public String isExportFormatSupported(String mimeType) { + if (KMLConstants.KML_MIME_TYPE.equalsIgnoreCase(mimeType)) { return FORMAT_SUPPORTED; + } return Arrays.binarySearch(SHAPE_CONTENT_TYPES, mimeType) >= 0 ? FORMAT_SUPPORTED : FORMAT_NOT_SUPPORTED; } - public void export(String mimeType, Object output) throws IOException, UnsupportedOperationException - { - if (mimeType == null) - { + public void export(String mimeType, Object output) throws IOException, UnsupportedOperationException { + if (mimeType == null) { String message = Logging.getMessage("nullValue.Format"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (output == null) - { + if (output == null) { String message = Logging.getMessage("nullValue.OutputBufferIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - try - { + try { this.doExport(mimeType, output); - } - catch (XMLStreamException e) - { + } catch (XMLStreamException e) { Logging.logger().throwing(getClass().getName(), "export", e); throw new IOException(e); } } - protected void doExport(String mimeType, Object output) throws IOException, XMLStreamException - { + protected void doExport(String mimeType, Object output) throws IOException, XMLStreamException { XMLStreamWriter xmlWriter = null; XMLOutputFactory factory = XMLOutputFactory.newInstance(); boolean closeWriterWhenFinished = true; - if (output instanceof XMLStreamWriter) - { + if (output instanceof XMLStreamWriter) { xmlWriter = (XMLStreamWriter) output; closeWriterWhenFinished = false; - } - else if (output instanceof Writer) - { + } else if (output instanceof Writer) { xmlWriter = factory.createXMLStreamWriter((Writer) output); - } - else if (output instanceof OutputStream) - { + } else if (output instanceof OutputStream) { xmlWriter = factory.createXMLStreamWriter((OutputStream) output); } - if (xmlWriter == null) - { + if (xmlWriter == null) { String message = Logging.getMessage("Export.UnsupportedOutputObject"); Logging.logger().warning(message); throw new IllegalArgumentException(message); } - if (KMLConstants.KML_MIME_TYPE.equals(mimeType)) + if (KMLConstants.KML_MIME_TYPE.equals(mimeType)) { exportAsKML(xmlWriter); - else + } else { exportAsXML(xmlWriter); + } xmlWriter.flush(); - if (closeWriterWhenFinished) + if (closeWriterWhenFinished) { xmlWriter.close(); + } } - protected void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException - { + protected void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException { xmlWriter.writeStartElement("Shapefile"); xmlWriter.writeCharacters("\n"); - while (this.hasNext()) - { - try - { + while (this.hasNext()) { + try { ShapefileRecord nr = this.nextRecord(); - if (nr == null) + if (nr == null) { continue; + } nr.exportAsXML(xmlWriter); xmlWriter.writeCharacters("\n"); - } - catch (Exception e) - { + } catch (Exception e) { String message = Logging.getMessage("Export.Exception.ShapefileRecord"); Logging.logger().log(Level.WARNING, message, e); @@ -2210,20 +2186,16 @@ protected void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStr xmlWriter.writeEndElement(); // Shapefile } - protected void exportAsKML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException - { - while (this.hasNext()) - { - try - { + protected void exportAsKML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException { + while (this.hasNext()) { + try { ShapefileRecord nr = this.nextRecord(); - if (nr == null) + if (nr == null) { continue; + } nr.exportAsKML(xmlWriter); - } - catch (Exception e) - { + } catch (Exception e) { String message = Logging.getMessage("Export.Exception.ShapefileRecord"); Logging.logger().log(Level.WARNING, message, e); @@ -2232,10 +2204,8 @@ protected void exportAsKML(XMLStreamWriter xmlWriter) throws IOException, XMLStr } } - public void printInfo(boolean printCoordinates) - { - while (this.hasNext()) - { + public void printInfo(boolean printCoordinates) { + while (this.hasNext()) { this.nextRecord().printInfo(printCoordinates); } } diff --git a/src/gov/nasa/worldwind/formats/shapefile/ShapefileLayerFactory.java b/src/gov/nasa/worldwind/formats/shapefile/ShapefileLayerFactory.java index 578a945938..303469d234 100644 --- a/src/gov/nasa/worldwind/formats/shapefile/ShapefileLayerFactory.java +++ b/src/gov/nasa/worldwind/formats/shapefile/ShapefileLayerFactory.java @@ -25,7 +25,6 @@ * NASA World Wind Java (WWJ) can be found in the WorldWindJava-v2.2 3rd-party * notices and licenses PDF found in code directory. */ - package gov.nasa.worldwind.formats.shapefile; import gov.nasa.worldwind.*; @@ -42,63 +41,78 @@ import java.util.Map; /** - * A factory that creates {@link gov.nasa.worldwind.layers.Layer} instances from a shapefile layer configuration source - * or a shapefile source. + * A factory that creates {@link gov.nasa.worldwind.layers.Layer} instances from + * a shapefile layer configuration source or a shapefile source. *

      Shapefile Geometry Conversion

      *

      - * Shapefile geometries are mapped to WorldWind objects as shown in the following table. - *
      WorldWind Shapefile Mapping
      Shapefile GeometryWorldWind Object
      Point{@link - * gov.nasa.worldwind.render.PointPlacemark}
      MultiPointList of {@link + * Shapefile geometries are mapped to WorldWind objects as shown in the + * following table. + * + *
      WorldWind Shapefile Mapping
      Shapefile + * GeometryWorldWind Object
      Point{@link + * gov.nasa.worldwind.render.PointPlacemark}
      MultiPointList of {@link * gov.nasa.worldwind.render.PointPlacemark}
      Polyline{@link * gov.nasa.worldwind.formats.shapefile.ShapefilePolylines}
      Polygon{@link * gov.nasa.worldwind.formats.shapefile.ShapefilePolygons}
      *

      - * In addition, if the DBase attributes file associated with the shapefile has an attribute named "height" or "hgt", the - * shapes in the shapefile are mapped to {@link gov.nasa.worldwind.formats.shapefile.ShapefileExtrudedPolygons}. + * In addition, if the DBase attributes file associated with the shapefile has + * an attribute named "height" or "hgt", the shapes in the shapefile are mapped + * to {@link gov.nasa.worldwind.formats.shapefile.ShapefileExtrudedPolygons}. *

      Shapefile Attributes

      *

      - * Shapefiles may have associated with them a DBase attributes file. This class provides a mechanism for mapping - * attribute names in the DBase file to keys assigned to the created shapes. The mapping is specified as key/value - * pairs, the key is the attribute name in the shapefile's DBase attributes file, the value is the key name to attach to - * the created shape to hold the value of the specified attribute. Thus, for example, the value of per-record "NAME" - * fields in the DBase attributes may be mapped to a {@link gov.nasa.worldwind.avlist.AVKey#DISPLAY_NAME} key in the - * av-list of the created shapes corresponding to each record. The mapping's key/value pairs are specified using {@link + * Shapefiles may have associated with them a DBase attributes file. This class + * provides a mechanism for mapping attribute names in the DBase file to keys + * assigned to the created shapes. The mapping is specified as key/value pairs, + * the key is the attribute name in the shapefile's DBase attributes file, the + * value is the key name to attach to the created shape to hold the value of the + * specified attribute. Thus, for example, the value of per-record "NAME" fields + * in the DBase attributes may be mapped to a + * {@link gov.nasa.worldwind.avlist.AVKey#DISPLAY_NAME} key in the av-list of + * the created shapes corresponding to each record. The mapping's key/value + * pairs are specified using {@link * #setDBaseMappings(gov.nasa.worldwind.avlist.AVList)}. *

      - * The rendering attributes applied to the created shapes may be specified to this class, either via the attribute - * accessors of this class or a configuration file passed to {@link #createFromConfigSource(Object, + * The rendering attributes applied to the created shapes may be specified to + * this class, either via the attribute accessors of this class or a + * configuration file passed to {@link #createFromConfigSource(Object, * gov.nasa.worldwind.avlist.AVList)}. *

      - * The key-value attributes and the rendering attributes of certain created shapes may be specified programmatically - * using a ShapefileRenderable.AttributeDelegate. The delegate is called for each shapefile record encountered during - * parsing, after this factory applies its DBase attribute mapping and its default rendering attributes. Currently, - * attribute delegates are called when parsing shapefiles containing polylines, polygons or extruded polygons. - * shapefiles containing points or multi-points ignore the attribute delegate. The delegate is specified using {@link + * The key-value attributes and the rendering attributes of certain created + * shapes may be specified programmatically using a + * ShapefileRenderable.AttributeDelegate. The delegate is called for each + * shapefile record encountered during parsing, after this factory applies its + * DBase attribute mapping and its default rendering attributes. Currently, + * attribute delegates are called when parsing shapefiles containing polylines, + * polygons or extruded polygons. shapefiles containing points or multi-points + * ignore the attribute delegate. The delegate is specified using {@link * #setAttributeDelegate(gov.nasa.worldwind.formats.shapefile.ShapefileRenderable.AttributeDelegate)}. * * @author tag * @version $Id: ShapefileLayerFactory.java 2348 2014-09-25 23:35:46Z dcollins $ */ -public class ShapefileLayerFactory implements Factory, ShapefileRenderable.AttributeDelegate -{ +public class ShapefileLayerFactory implements Factory, ShapefileRenderable.AttributeDelegate { + /** - * Defines an interface for receiving notifications when shapefile parsing completes or encounters an exception. - * This interface's methods are executed on a separate thread created by the factory. Implementations must - * synchronize access to objects that are not thread safe. + * Defines an interface for receiving notifications when shapefile parsing + * completes or encounters an exception. This interface's methods are + * executed on a separate thread created by the factory. Implementations + * must synchronize access to objects that are not thread safe. */ - public interface CompletionCallback - { + public interface CompletionCallback { + /** - * Called when shapefile parsing and geometry conversion completes. Always called before the factory's thread - * terminates. Executed on a separate thread created by the factory. + * Called when shapefile parsing and geometry conversion completes. + * Always called before the factory's thread terminates. Executed on a + * separate thread created by the factory. * * @param result The layer created by this factory. */ void completion(Object result); /** - * Called if exception occurs during shapefile parsing or shapefile geometry conversion. May be called multiple - * times during shapefile parsing. Executed on a separate thread created by the factory. + * Called if exception occurs during shapefile parsing or shapefile + * geometry conversion. May be called multiple times during shapefile + * parsing. Executed on a separate thread created by the factory. * * @param e The exception thrown. */ @@ -113,186 +127,203 @@ public interface CompletionCallback protected ShapefileRenderable.AttributeDelegate attributeDelegate; /** - * Indicates the mappings between shapefile attribute names and av-list keys attached to created shapes. + * Indicates the mappings between shapefile attribute names and av-list keys + * attached to created shapes. * * @return The mappings. */ - public AVList getDBaseMappings() - { + public AVList getDBaseMappings() { return dBaseMappings; } /** - * Specifies the mapping of shapefile attribute names to keys attached to created shapes. For each shapefile record, - * this class assigns the value of the named attribute for that record to the specified key on the shape created for - * that record. The key is associated only when the shapefile record's attributes contains the specified attribute - * name. + * Specifies the mapping of shapefile attribute names to keys attached to + * created shapes. For each shapefile record, this class assigns the value + * of the named attribute for that record to the specified key on the shape + * created for that record. The key is associated only when the shapefile + * record's attributes contains the specified attribute name. * - * @param dBaseMappings The mappings. May be null, in which case no mapping occurs. + * @param dBaseMappings The mappings. May be null, in which case no mapping + * occurs. */ - public void setDBaseMappings(AVList dBaseMappings) - { + public void setDBaseMappings(AVList dBaseMappings) { this.dBaseMappings = dBaseMappings; } /** - * Indicates the normal shape attributes assigned to non-point shapes created by this class. + * Indicates the normal shape attributes assigned to non-point shapes + * created by this class. * * @return The normal attributes assigned to non-point shapes. */ - public ShapeAttributes getNormalShapeAttributes() - { + public ShapeAttributes getNormalShapeAttributes() { return normalShapeAttributes; } /** - * Specifies the normal attributes assigned to non-point shapes created by this class. + * Specifies the normal attributes assigned to non-point shapes created by + * this class. * - * @param normalShapeAttributes The normal attributes assigned to non-point shapes. + * @param normalShapeAttributes The normal attributes assigned to non-point + * shapes. */ - public void setNormalShapeAttributes(ShapeAttributes normalShapeAttributes) - { + public void setNormalShapeAttributes(ShapeAttributes normalShapeAttributes) { this.normalShapeAttributes = normalShapeAttributes; } /** - * Indicates the highlight shape attributes assigned to non-point shapes created by this class. + * Indicates the highlight shape attributes assigned to non-point shapes + * created by this class. * * @return The highlight attributes assigned to non-point shapes. */ - public ShapeAttributes getHighlightShapeAttributes() - { + public ShapeAttributes getHighlightShapeAttributes() { return highlightShapeAttributes; } /** - * Specifies the highlight attributes assigned to non-point shapes created by this class. + * Specifies the highlight attributes assigned to non-point shapes created + * by this class. * - * @param highlightShapeAttributes The highlight attributes assigned to non-point shapes. + * @param highlightShapeAttributes The highlight attributes assigned to + * non-point shapes. */ - public void setHighlightShapeAttributes(ShapeAttributes highlightShapeAttributes) - { + public void setHighlightShapeAttributes(ShapeAttributes highlightShapeAttributes) { this.highlightShapeAttributes = highlightShapeAttributes; } /** - * Indicates the normal attributes assigned to point shapes created by this class. + * Indicates the normal attributes assigned to point shapes created by this + * class. * * @return The normal attributes assigned to point shapes. */ - public PointPlacemarkAttributes getNormalPointAttributes() - { + public PointPlacemarkAttributes getNormalPointAttributes() { return normalPointAttributes; } /** - * Specifies the normal attributes assigned to point shapes created by this class. + * Specifies the normal attributes assigned to point shapes created by this + * class. * - * @param normalPointAttributes The normal attributes assigned to point shapes. + * @param normalPointAttributes The normal attributes assigned to point + * shapes. */ - public void setNormalPointAttributes(PointPlacemarkAttributes normalPointAttributes) - { + public void setNormalPointAttributes(PointPlacemarkAttributes normalPointAttributes) { this.normalPointAttributes = normalPointAttributes; } /** - * Indicates the highlight attributes assigned to point shapes created by this class. + * Indicates the highlight attributes assigned to point shapes created by + * this class. * * @return The highlight attributes assigned to point shapes. */ - public PointPlacemarkAttributes getHighlightPointAttributes() - { + public PointPlacemarkAttributes getHighlightPointAttributes() { return highlightPointAttributes; } /** - * Specifies the highlight attributes assigned to point shapes created by this class. + * Specifies the highlight attributes assigned to point shapes created by + * this class. * - * @param highlightPointAttributes The highlight attributes assigned to point shapes. + * @param highlightPointAttributes The highlight attributes assigned to + * point shapes. */ - public void setHighlightPointAttributes(PointPlacemarkAttributes highlightPointAttributes) - { + public void setHighlightPointAttributes(PointPlacemarkAttributes highlightPointAttributes) { this.highlightPointAttributes = highlightPointAttributes; } /** - * Indicates the attribute delegate called for each shapefile record encountered during parsing. + * Indicates the attribute delegate called for each shapefile record + * encountered during parsing. * * @return The attribute delegate called for each shapefile record. */ - public ShapefileRenderable.AttributeDelegate getAttributeDelegate() - { + public ShapefileRenderable.AttributeDelegate getAttributeDelegate() { return this.attributeDelegate; } /** - * Specifies an attribute delegate to call for each shapefile record encountered during parsing. The delegate is - * called after this factory applies its DBase attribute mapping and its default rendering attributes. + * Specifies an attribute delegate to call for each shapefile record + * encountered during parsing. The delegate is called after this factory + * applies its DBase attribute mapping and its default rendering attributes. *

      - * Currently, attribute delegates are called when parsing shapefiles containing polylines, polygons or extruded - * polygons. shapefiles containing points or multi-points ignore the attribute delegate. + * Currently, attribute delegates are called when parsing shapefiles + * containing polylines, polygons or extruded polygons. shapefiles + * containing points or multi-points ignore the attribute delegate. * - * @param attributeDelegate The attribute delegate to call for each shapefile record. + * @param attributeDelegate The attribute delegate to call for each + * shapefile record. */ - public void setAttributeDelegate(ShapefileRenderable.AttributeDelegate attributeDelegate) - { + public void setAttributeDelegate(ShapefileRenderable.AttributeDelegate attributeDelegate) { this.attributeDelegate = attributeDelegate; } /** - * Applies this factory's DBase attribute mapping and default rendering attributes to the specified records. If an - * attribute delegate has been specified using {@link #setAttributeDelegate(gov.nasa.worldwind.formats.shapefile.ShapefileRenderable.AttributeDelegate)}, + * Applies this factory's DBase attribute mapping and default rendering + * attributes to the specified records. If an attribute delegate has been + * specified using + * {@link #setAttributeDelegate(gov.nasa.worldwind.formats.shapefile.ShapefileRenderable.AttributeDelegate)}, * this calls the attribute delegate before exiting. * - * @param shapefileRecord The shapefile record used to create the ShapefileRenderable.Record. - * @param renderableRecord The ShapefileRenderable.Record to assign attributes for. + * @param shapefileRecord The shapefile record used to create the + * ShapefileRenderable.Record. + * @param renderableRecord The ShapefileRenderable.Record to assign + * attributes for. */ @Override - public void assignAttributes(ShapefileRecord shapefileRecord, ShapefileRenderable.Record renderableRecord) - { - if (this.dBaseMappings != null) - { + public void assignAttributes(ShapefileRecord shapefileRecord, ShapefileRenderable.Record renderableRecord) { + if (this.dBaseMappings != null) { AVList mappings = this.applyMappings(shapefileRecord.getAttributes(), this.dBaseMappings); - if (mappings != null) + if (mappings != null) { renderableRecord.setValues(mappings); + } } - if (this.attributeDelegate != null) - { + if (this.attributeDelegate != null) { this.attributeDelegate.assignAttributes(shapefileRecord, renderableRecord); } } /** - * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general configuration source. The source can be one of - * the following:

      • a {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link - * java.io.InputStream}
      • {@link Element}
      • a {@link String} holding a file name, a name of a resource - * on the classpath, or a string representation of a URL
      + * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general + * configuration source. The source can be one of the following:
      • a + * {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link + * java.io.InputStream}
      • {@link Element}
      • a {@link String} + * holding a file name, a name of a resource on the classpath, or a string + * representation of a URL
      *

      - * The XML configuration file indicated by the source must contain the shapefile location, and may contain elements - * specifying shapefile attribute mappings, shape attributes to assign to created shapes, and layer properties. + * The XML configuration file indicated by the source must contain the + * shapefile location, and may contain elements specifying shapefile + * attribute mappings, shape attributes to assign to created shapes, and + * layer properties. *

      - * This returns with the new layer immediately, but executes shapefile parsing and shapefile geometry conversion on - * a separate thread. Shapefile geometry is added to the returned layer as it becomes available. In order to receive - * notifications when execution completes or if an exception occurs, use {@link #createFromConfigSource(Object, + * This returns with the new layer immediately, but executes shapefile + * parsing and shapefile geometry conversion on a separate thread. Shapefile + * geometry is added to the returned layer as it becomes available. In order + * to receive notifications when execution completes or if an exception + * occurs, use {@link #createFromConfigSource(Object, * gov.nasa.worldwind.avlist.AVList, gov.nasa.worldwind.formats.shapefile.ShapefileLayerFactory.CompletionCallback)} * and specify a completion callback. * - * @param configSource the configuration source. See above for supported types. - * @param params Key/value pairs to associate with the created layer. Values specified here override - * corresponding values specified within the configuration element. + * @param configSource the configuration source. See above for supported + * types. + * @param params Key/value pairs to associate with the created layer. Values + * specified here override corresponding values specified within the + * configuration element. * * @return a Layer, as described by the XML configuration file. * - * @throws IllegalArgumentException if the configuration file name is null or an empty string. - * @throws WWRuntimeException if object creation fails. The exception indicating the source of the failure is - * included as the {@link Exception#initCause(Throwable)}. + * @throws IllegalArgumentException if the configuration file name is null + * or an empty string. + * @throws WWRuntimeException if object creation fails. The exception + * indicating the source of the failure is included as the + * {@link Exception#initCause(Throwable)}. */ @Override - public Object createFromConfigSource(Object configSource, AVList params) - { - if (WWUtil.isEmpty(configSource)) - { + public Object createFromConfigSource(Object configSource, AVList params) { + if (WWUtil.isEmpty(configSource)) { String message = Logging.getMessage("generic.ConfigurationSourceIsInvalid", configSource); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -302,38 +333,47 @@ public Object createFromConfigSource(Object configSource, AVList params) } /** - * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general configuration source. The source can be one of - * the following:

      • a {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link - * java.io.InputStream}
      • {@link Element}
      • a {@link String} holding a file name, a name of a resource - * on the classpath, or a string representation of a URL
      + * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general + * configuration source. The source can be one of the following:
      • a + * {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link + * java.io.InputStream}
      • {@link Element}
      • a {@link String} + * holding a file name, a name of a resource on the classpath, or a string + * representation of a URL
      *

      - * The XML configuration file indicated by the source must contain the shapefile location, and may contain elements - * specifying shapefile attribute mappings, shape attributes to assign to created shapes, and layer properties. + * The XML configuration file indicated by the source must contain the + * shapefile location, and may contain elements specifying shapefile + * attribute mappings, shape attributes to assign to created shapes, and + * layer properties. *

      - * This returns with the new layer immediately, but executes shapefile parsing and shapefile geometry conversion on - * a separate thread. Shapefile geometry is added to the returned layer as it becomes available. Once parsing - * completes, this calls the callback's completion method with the completed layer as the sole argument. + * This returns with the new layer immediately, but executes shapefile + * parsing and shapefile geometry conversion on a separate thread. Shapefile + * geometry is added to the returned layer as it becomes available. Once + * parsing completes, this calls the callback's completion method with the + * completed layer as the sole argument. *

      - * If an exception occurs during execution, this catches the exception and forwards it to the callback's exception - * method. When an exception causes layer parsing or geometry conversion to fail, this calls the callback's + * If an exception occurs during execution, this catches the exception and + * forwards it to the callback's exception method. When an exception causes + * layer parsing or geometry conversion to fail, this calls the callback's * completion method before the separate thread terminates. * - * @param configSource the configuration source. See above for supported types. - * @param params Key/value pairs to associate with the created layer. Values specified here override - * corresponding values specified within the configuration element. - * @param callback a callback to notify when shapefile parsing completes or encounters an exception. May be - * null. + * @param configSource the configuration source. See above for supported + * types. + * @param params Key/value pairs to associate with the created layer. Values + * specified here override corresponding values specified within the + * configuration element. + * @param callback a callback to notify when shapefile parsing completes or + * encounters an exception. May be null. * * @return a Layer, as described by the XML configuration file. * - * @throws IllegalArgumentException if the configuration file name is null or an empty string. - * @throws WWRuntimeException if object creation fails. The exception indicating the source of the failure is - * included as the {@link Exception#initCause(Throwable)}. + * @throws IllegalArgumentException if the configuration file name is null + * or an empty string. + * @throws WWRuntimeException if object creation fails. The exception + * indicating the source of the failure is included as the + * {@link Exception#initCause(Throwable)}. */ - public Object createFromConfigSource(Object configSource, AVList params, CompletionCallback callback) - { - if (WWUtil.isEmpty(configSource)) - { + public Object createFromConfigSource(Object configSource, AVList params, CompletionCallback callback) { + if (WWUtil.isEmpty(configSource)) { String message = Logging.getMessage("generic.ConfigurationSourceIsInvalid", configSource); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -341,21 +381,16 @@ public Object createFromConfigSource(Object configSource, AVList params, Complet Object o = null; - try - { - if (configSource instanceof Element) - { + try { + if (configSource instanceof Element) { o = this.doCreateFromElement((Element) configSource, params, callback); - } - else - { + } else { Document doc = WWXML.openDocument(configSource); - if (doc != null) + if (doc != null) { o = this.doCreateFromElement(doc.getDocumentElement(), params, callback); + } } - } - catch (Exception e) - { + } catch (Exception e) { String msg = Logging.getMessage("generic.CreationFromConfigurationFileFailed", configSource); throw new WWRuntimeException(msg, e); } @@ -364,32 +399,37 @@ public Object createFromConfigSource(Object configSource, AVList params, Complet } /** - * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general shapefile source. The source can be one of the - * following:

      • a {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link - * java.io.InputStream}
      • {@link Shapefile}
      • a {@link String} holding a file name, a name of a - * resource on the classpath, or a string representation of a URL
      + * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general + * shapefile source. The source can be one of the following:
      • a + * {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link + * java.io.InputStream}
      • {@link Shapefile}
      • a {@link String} + * holding a file name, a name of a resource on the classpath, or a string + * representation of a URL
      *

      - * This returns with the new layer immediately, but executes shapefile parsing and shapefile geometry conversion on - * a separate thread. Shapefile geometry is added to the returned layer as it becomes available. In order to receive - * notifications when execution completes or if an exception occurs, use {@link #createFromConfigSource(Object, + * This returns with the new layer immediately, but executes shapefile + * parsing and shapefile geometry conversion on a separate thread. Shapefile + * geometry is added to the returned layer as it becomes available. In order + * to receive notifications when execution completes or if an exception + * occurs, use {@link #createFromConfigSource(Object, * gov.nasa.worldwind.avlist.AVList, gov.nasa.worldwind.formats.shapefile.ShapefileLayerFactory.CompletionCallback)} * and specify a completion callback. *

      - * If the source is a Shapefile instance, it is the responsibility of the caller to close the shapefile after this - * factory completes execution. + * If the source is a Shapefile instance, it is the responsibility of the + * caller to close the shapefile after this factory completes execution. * - * @param shapefileSource the shapefile source. See above for supported types. + * @param shapefileSource the shapefile source. See above for supported + * types. * * @return a Layer that renders the shapefile's contents. * - * @throws IllegalArgumentException if the shapefile file name is null or an empty string. - * @throws WWRuntimeException if object creation fails. The exception indicating the source of the failure is - * included as the {@link Exception#initCause(Throwable)}. + * @throws IllegalArgumentException if the shapefile file name is null or an + * empty string. + * @throws WWRuntimeException if object creation fails. The exception + * indicating the source of the failure is included as the + * {@link Exception#initCause(Throwable)}. */ - public Object createFromShapefileSource(Object shapefileSource) - { - if (WWUtil.isEmpty(shapefileSource)) - { + public Object createFromShapefileSource(Object shapefileSource) { + if (WWUtil.isEmpty(shapefileSource)) { String message = Logging.getMessage("generic.ShapefileSourceIsInvalid", shapefileSource); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -399,36 +439,42 @@ public Object createFromShapefileSource(Object shapefileSource) } /** - * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general shapefile source. The source can be one of the - * following:

      • a {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link - * java.io.InputStream}
      • {@link Shapefile}
      • a {@link String} holding a file name, a name of a - * resource on the classpath, or a string representation of a URL
      + * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general + * shapefile source. The source can be one of the following:
      • a + * {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link + * java.io.InputStream}
      • {@link Shapefile}
      • a {@link String} + * holding a file name, a name of a resource on the classpath, or a string + * representation of a URL
      *

      - * This returns with the new layer immediately, but executes shapefile parsing and shapefile geometry conversion on - * a separate thread. Shapefile geometry is added to the returned layer as it becomes available. Once parsing - * completes, this calls the callback's completion method with the completed layer as the sole argument. + * This returns with the new layer immediately, but executes shapefile + * parsing and shapefile geometry conversion on a separate thread. Shapefile + * geometry is added to the returned layer as it becomes available. Once + * parsing completes, this calls the callback's completion method with the + * completed layer as the sole argument. *

      - * If an exception occurs during execution, this catches the exception and forwards it to the callback's exception - * method. When an exception causes layer parsing or geometry conversion to fail, this calls the callback's + * If an exception occurs during execution, this catches the exception and + * forwards it to the callback's exception method. When an exception causes + * layer parsing or geometry conversion to fail, this calls the callback's * completion method before the separate thread terminates. *

      - * If the source is a Shapefile instance, it is the responsibility of the caller to close the shapefile after this - * factory completes execution. + * If the source is a Shapefile instance, it is the responsibility of the + * caller to close the shapefile after this factory completes execution. * - * @param shapefileSource the shapefile source. See above for supported types. - * @param callback a callback to notify when shapefile parsing completes or encounters an exception. May be - * null. + * @param shapefileSource the shapefile source. See above for supported + * types. + * @param callback a callback to notify when shapefile parsing completes or + * encounters an exception. May be null. * * @return a Layer that renders the shapefile's contents. * - * @throws IllegalArgumentException if the shapefile file name is null or an empty string. - * @throws WWRuntimeException if object creation fails. The exception indicating the source of the failure is - * included as the {@link Exception#initCause(Throwable)}. + * @throws IllegalArgumentException if the shapefile file name is null or an + * empty string. + * @throws WWRuntimeException if object creation fails. The exception + * indicating the source of the failure is included as the + * {@link Exception#initCause(Throwable)}. */ - public Object createFromShapefileSource(Object shapefileSource, CompletionCallback callback) - { - if (WWUtil.isEmpty(shapefileSource)) - { + public Object createFromShapefileSource(Object shapefileSource, CompletionCallback callback) { + if (WWUtil.isEmpty(shapefileSource)) { String message = Logging.getMessage("generic.ShapefileSourceIsInvalid", shapefileSource); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -436,12 +482,9 @@ public Object createFromShapefileSource(Object shapefileSource, CompletionCallba Object o; - try - { + try { o = this.doCreateFromShapefile(shapefileSource, callback); - } - catch (Exception e) - { + } catch (Exception e) { String msg = Logging.getMessage("generic.CreationFromShapefileSourceFailed", shapefileSource); throw new WWRuntimeException(msg, e); } @@ -450,32 +493,34 @@ public Object createFromShapefileSource(Object shapefileSource, CompletionCallba } /** - * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general shapefile layer configuration element. The - * element must contain the shapefile location, and may contain elements specifying shapefile attribute mappings, - * shape attributes to assign to created shapes, and layer properties. + * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general + * shapefile layer configuration element. The element must contain the + * shapefile location, and may contain elements specifying shapefile + * attribute mappings, shape attributes to assign to created shapes, and + * layer properties. * * @param domElement an XML element describing the layer. - * @param params any properties to apply when creating the layer. - * @param callback A callback to notify when shapefile parsing completes or encounters an exception. May be null. + * @param params any properties to apply when creating the layer. + * @param callback A callback to notify when shapefile parsing completes or + * encounters an exception. May be null. * * @return a Layer, as described by the specified description. * * @throws Exception if an exception occurs during creation. */ protected Object doCreateFromElement(Element domElement, AVList params, CompletionCallback callback) - throws Exception - { + throws Exception { String shapefileLocation = WWXML.getText(domElement, "ShapefileLocation"); - if (WWUtil.isEmpty(shapefileLocation)) - { + if (WWUtil.isEmpty(shapefileLocation)) { String msg = Logging.getMessage("SHP.ShapefileLocationUnspecified"); throw new WWRuntimeException(msg); } RenderableLayer layer = new RenderableLayer(); - if (params == null) + if (params == null) { params = new AVListImpl(); + } // Common layer properties. AbstractLayer.getLayerConfigParams(domElement, params); @@ -499,20 +544,24 @@ protected Object doCreateFromElement(Element domElement, AVList params, Completi this.setHighlightPointAttributes(element != null ? this.collectPointAttributes(element) : null); Double d = (Double) params.getValue(AVKey.OPACITY); - if (d != null) + if (d != null) { layer.setOpacity(d); + } d = (Double) params.getValue(AVKey.MAX_ACTIVE_ALTITUDE); - if (d != null) + if (d != null) { layer.setMaxActiveAltitude(d); + } d = (Double) params.getValue(AVKey.MIN_ACTIVE_ALTITUDE); - if (d != null) + if (d != null) { layer.setMinActiveAltitude(d); + } Boolean b = (Boolean) params.getValue(AVKey.PICK_ENABLED); - if (b != null) + if (b != null) { layer.setPickEnabled(b); + } this.createShapefileLayer(shapefileLocation, layer, callback); @@ -520,21 +569,23 @@ protected Object doCreateFromElement(Element domElement, AVList params, Completi } /** - * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general shapefile source. The source can be one of the - * following:

      • a {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link - * java.io.InputStream}
      • {@link Shapefile}
      • a {@link String} holding a file name, a name of a - * resource on the classpath, or a string representation of a URL
      + * Creates a {@link gov.nasa.worldwind.layers.Layer} from a general + * shapefile source. The source can be one of the following:
      • a + * {@link java.net.URL}
      • a {@link java.io.File}
      • a {@link + * java.io.InputStream}
      • {@link Shapefile}
      • a {@link String} + * holding a file name, a name of a resource on the classpath, or a string + * representation of a URL
      * - * @param shapefileSource the shapefile source. See above for supported types. - * @param callback A callback to notify when shapefile parsing completes or encounters an exception. May be - * null. + * @param shapefileSource the shapefile source. See above for supported + * types. + * @param callback A callback to notify when shapefile parsing completes or + * encounters an exception. May be null. * * @return a Layer that renders the shapefile's contents. * * @throws Exception if an exception occurs during creation. */ - protected Object doCreateFromShapefile(Object shapefileSource, CompletionCallback callback) throws Exception - { + protected Object doCreateFromShapefile(Object shapefileSource, CompletionCallback callback) throws Exception { RenderableLayer layer = new RenderableLayer(); this.createShapefileLayer(shapefileSource, layer, callback); @@ -543,69 +594,61 @@ protected Object doCreateFromShapefile(Object shapefileSource, CompletionCallbac } protected void createShapefileLayer(final Object shapefileSource, final RenderableLayer layer, - final CompletionCallback callback) - { - WorldWind.getScheduledTaskService().addTask(new Runnable() - { + final CompletionCallback callback) { + WorldWind.getScheduledTaskService().addTask(new Runnable() { @Override - public void run() - { + public void run() { Shapefile shp = null; - try - { + try { shp = loadShapefile(shapefileSource); assembleShapefileLayer(shp, layer); - } - catch (Exception e) - { - if (callback != null) + } catch (Exception e) { + if (callback != null) { callback.exception(e); - } - finally - { - if (callback != null) + } + } finally { + if (callback != null) { callback.completion(layer); + } if (shapefileSource != shp) // close the shapefile if we created it + { WWIO.closeStream(shp, shapefileSource.toString()); + } } } }); } - protected Shapefile loadShapefile(Object shapefileSource) - { + protected Shapefile loadShapefile(Object shapefileSource) { return (shapefileSource instanceof Shapefile) ? (Shapefile) shapefileSource : new Shapefile(shapefileSource); } - protected void assembleShapefileLayer(Shapefile shp, RenderableLayer layer) - { + protected void assembleShapefileLayer(Shapefile shp, RenderableLayer layer) { this.addRenderablesForShapefile(shp, layer); this.addPropertiesForShapefile(shp, layer); } - protected AVList collectDBaseMappings(Element domElement, XPath xpath) - { - try - { + protected AVList collectDBaseMappings(Element domElement, XPath xpath) { + try { Element[] elements = WWXML.getElements(domElement, "AttributeMapping", xpath); - if (elements == null || elements.length == 0) + if (elements == null || elements.length == 0) { return null; + } AVList attrMappings = new AVListImpl(); - for (Element el : elements) - { + for (Element el : elements) { String prop = xpath.evaluate("@attributeName", el); String value = xpath.evaluate("@mapToKey", el); - if (WWUtil.isEmpty(prop) || WWUtil.isEmpty(value)) + if (WWUtil.isEmpty(prop) || WWUtil.isEmpty(value)) { continue; + } attrMappings.setValue(prop, value); } return attrMappings; - } - catch (XPathExpressionException e) // should not occur, but log just if it does + } catch (XPathExpressionException e) // should not occur, but log just if it does { String message = Logging.getMessage("XML.InvalidXPathExpression", "internal expression"); Logging.logger().log(java.util.logging.Level.WARNING, message, e); @@ -613,119 +656,121 @@ protected AVList collectDBaseMappings(Element domElement, XPath xpath) } } - protected PointPlacemarkAttributes collectPointAttributes(Element attrElement) - { + protected PointPlacemarkAttributes collectPointAttributes(Element attrElement) { XPathFactory xpFactory = XPathFactory.newInstance(); XPath xpath = xpFactory.newXPath(); PointPlacemarkAttributes attributes = new PointPlacemarkAttributes(); String imageAddress = WWXML.getText(attrElement, "ImageAddress", xpath); - if (!WWUtil.isEmpty(imageAddress)) + if (!WWUtil.isEmpty(imageAddress)) { attributes.setImageAddress(imageAddress); + } Double scale = WWXML.getDouble(attrElement, "Scale", xpath); - if (scale != null) + if (scale != null) { attributes.setScale(scale); + } Color imageColor = WWXML.getColor(attrElement, "ImageColor", xpath); - if (imageColor != null) + if (imageColor != null) { attributes.setImageColor(imageColor); + } Double width = WWXML.getDouble(attrElement, "LineWidth", xpath); - if (width != null) + if (width != null) { attributes.setLineWidth(width); + } Double labelScale = WWXML.getDouble(attrElement, "LabelScale", xpath); - if (labelScale != null) + if (labelScale != null) { attributes.setLabelScale(labelScale); + } Color labelColor = WWXML.getColor(attrElement, "LabelColor", xpath); - if (labelColor != null) + if (labelColor != null) { attributes.setLabelMaterial(new Material(labelColor)); + } Color lineColor = WWXML.getColor(attrElement, "LineColor", xpath); - if (lineColor != null) + if (lineColor != null) { attributes.setLabelMaterial(new Material(lineColor)); + } Boolean tf = WWXML.getBoolean(attrElement, "UsePointAsDefaultImage", xpath); - if (tf != null) + if (tf != null) { attributes.setUsePointAsDefaultImage(tf); + } return attributes; } - protected ShapeAttributes collectShapeAttributes(Element attrElement) - { + protected ShapeAttributes collectShapeAttributes(Element attrElement) { XPathFactory xpFactory = XPathFactory.newInstance(); XPath xpath = xpFactory.newXPath(); ShapeAttributes shapeAttributes = new BasicShapeAttributes(); Boolean tf = WWXML.getBoolean(attrElement, "DrawInterior", xpath); - if (tf != null) + if (tf != null) { shapeAttributes.setDrawInterior(tf); + } tf = WWXML.getBoolean(attrElement, "DrawOutline", xpath); - if (tf != null) + if (tf != null) { shapeAttributes.setDrawOutline(tf); + } Double opacity = WWXML.getDouble(attrElement, "InteriorOpacity", xpath); - if (opacity != null) + if (opacity != null) { shapeAttributes.setInteriorOpacity(opacity); + } opacity = WWXML.getDouble(attrElement, "OutlineOpacity", xpath); - if (opacity != null) + if (opacity != null) { shapeAttributes.setOutlineOpacity(opacity); + } Double width = WWXML.getDouble(attrElement, "OutlineWidth", xpath); - if (opacity != null) + if (opacity != null) { shapeAttributes.setOutlineWidth(width); + } Color color = WWXML.getColor(attrElement, "InteriorColor", xpath); - if (color != null) + if (color != null) { shapeAttributes.setInteriorMaterial(new Material(color)); + } color = WWXML.getColor(attrElement, "OutlineColor", xpath); - if (color != null) + if (color != null) { shapeAttributes.setOutlineMaterial(new Material(color)); + } return shapeAttributes; } - protected void addRenderablesForShapefile(Shapefile shp, RenderableLayer layer) - { - if (Shapefile.isPointType(shp.getShapeType())) - { + protected void addRenderablesForShapefile(Shapefile shp, RenderableLayer layer) { + if (Shapefile.isPointType(shp.getShapeType())) { this.addRenderablesForPoints(shp, layer); - } - else if (Shapefile.isMultiPointType(shp.getShapeType())) - { + } else if (Shapefile.isMultiPointType(shp.getShapeType())) { this.addRenderablesForMultiPoints(shp, layer); - } - else if (Shapefile.isPolylineType(shp.getShapeType())) - { + } else if (Shapefile.isPolylineType(shp.getShapeType())) { this.addRenderablesForPolylines(shp, layer); - } - else if (Shapefile.isPolygonType(shp.getShapeType())) - { + } else if (Shapefile.isPolygonType(shp.getShapeType())) { this.addRenderablesForPolygons(shp, layer); - } - else - { + } else { String msg = Logging.getMessage("generic.UnrecognizedShapeType", shp.getShapeType()); throw new WWRuntimeException(msg); } } - protected void addRenderablesForPoints(Shapefile shp, RenderableLayer layer) - { - while (shp.hasNext()) - { + protected void addRenderablesForPoints(Shapefile shp, RenderableLayer layer) { + while (shp.hasNext()) { ShapefileRecord record = shp.nextRecord(); - if (!Shapefile.isPointType(record.getShapeType())) + if (!Shapefile.isPointType(record.getShapeType())) { continue; + } AVList mappings = this.applyMappings(record.getAttributes(), this.dBaseMappings); @@ -734,102 +779,93 @@ protected void addRenderablesForPoints(Shapefile shp, RenderableLayer layer) } } - protected void addRenderablesForMultiPoints(Shapefile shp, RenderableLayer layer) - { - while (shp.hasNext()) - { + protected void addRenderablesForMultiPoints(Shapefile shp, RenderableLayer layer) { + while (shp.hasNext()) { ShapefileRecord record = shp.nextRecord(); - if (!Shapefile.isMultiPointType(record.getShapeType())) + if (!Shapefile.isMultiPointType(record.getShapeType())) { continue; + } AVList mappings = this.applyMappings(record.getAttributes(), this.dBaseMappings); Iterable iterable = ((ShapefileRecordMultiPoint) record).getPoints(0); - for (double[] point : iterable) - { + for (double[] point : iterable) { layer.addRenderable( - this.createPoint(record, point[1], point[0], mappings)); + this.createPoint(record, point[1], point[0], mappings)); } } } @SuppressWarnings({"UnusedDeclaration"}) - protected Renderable createPoint(ShapefileRecord record, double latDegrees, double lonDegrees, AVList mappings) - { + protected Renderable createPoint(ShapefileRecord record, double latDegrees, double lonDegrees, AVList mappings) { PointPlacemark placemark = new PointPlacemark(Position.fromDegrees(latDegrees, lonDegrees, 0)); placemark.setAltitudeMode(WorldWind.CLAMP_TO_GROUND); - if (this.normalPointAttributes != null) + if (this.normalPointAttributes != null) { placemark.setAttributes(this.normalPointAttributes); - if (this.highlightPointAttributes != null) + } + if (this.highlightPointAttributes != null) { placemark.setHighlightAttributes(this.highlightPointAttributes); + } - if (mappings != null) + if (mappings != null) { placemark.setValues(mappings); + } return placemark; } - protected void addRenderablesForPolylines(Shapefile shp, RenderableLayer layer) - { + protected void addRenderablesForPolylines(Shapefile shp, RenderableLayer layer) { ShapefilePolylines shape = new ShapefilePolylines(shp, this.normalShapeAttributes, - this.highlightShapeAttributes, this); + this.highlightShapeAttributes, this); layer.addRenderable(shape); } - protected void addRenderablesForPolygons(Shapefile shp, RenderableLayer layer) - { - if (ShapefileUtils.hasHeightAttribute(shp)) - { + protected void addRenderablesForPolygons(Shapefile shp, RenderableLayer layer) { + if (ShapefileUtils.hasHeightAttribute(shp)) { this.addRenderablesForExtrudedPolygons(shp, layer); - } - else - { + } else { this.addRenderablesForSurfacePolygons(shp, layer); } } - protected void addRenderablesForSurfacePolygons(Shapefile shp, RenderableLayer layer) - { + protected void addRenderablesForSurfacePolygons(Shapefile shp, RenderableLayer layer) { ShapefilePolygons shape = new ShapefilePolygons(shp, this.normalShapeAttributes, - this.highlightShapeAttributes, this); + this.highlightShapeAttributes, this); layer.addRenderable(shape); } - protected void addRenderablesForExtrudedPolygons(Shapefile shp, RenderableLayer layer) - { + protected void addRenderablesForExtrudedPolygons(Shapefile shp, RenderableLayer layer) { ShapefileExtrudedPolygons shape = new ShapefileExtrudedPolygons(shp, this.normalShapeAttributes, - this.highlightShapeAttributes, this); + this.highlightShapeAttributes, this); layer.addRenderable(shape); } - protected AVList applyMappings(DBaseRecord attrRecord, AVList attrMappings) - { - if (attrRecord == null || attrMappings == null) + protected AVList applyMappings(DBaseRecord attrRecord, AVList attrMappings) { + if (attrRecord == null || attrMappings == null) { return null; + } AVList mappings = new AVListImpl(); - for (Map.Entry mapping : attrMappings.getEntries()) - { + for (Map.Entry mapping : attrMappings.getEntries()) { Object attrValue = attrRecord.getValue(mapping.getKey()); - if (attrValue != null) + if (attrValue != null) { mappings.setValue((String) mapping.getValue(), attrValue); + } } return mappings.getEntries().size() > 0 ? mappings : null; } - protected void addPropertiesForShapefile(Shapefile shp, RenderableLayer layer) - { + protected void addPropertiesForShapefile(Shapefile shp, RenderableLayer layer) { if (layer.getValue(AVKey.DISPLAY_NAME) == null) // use the shapefile's display name when the layer is unnamed { layer.setValue(AVKey.DISPLAY_NAME, shp.getValue(AVKey.DISPLAY_NAME)); } - if (shp.getBoundingRectangle() != null) - { + if (shp.getBoundingRectangle() != null) { layer.setValue(AVKey.SECTOR, Sector.fromDegrees(shp.getBoundingRectangle())); } } diff --git a/src/gov/nasa/worldwind/formats/shapefile/ShapefileRecord.java b/src/gov/nasa/worldwind/formats/shapefile/ShapefileRecord.java index 1b1e443dff..9553c1ba2c 100644 --- a/src/gov/nasa/worldwind/formats/shapefile/ShapefileRecord.java +++ b/src/gov/nasa/worldwind/formats/shapefile/ShapefileRecord.java @@ -42,8 +42,8 @@ * @author Patrick Murris * @version $Id: ShapefileRecord.java 2303 2014-09-14 22:33:36Z dcollins $ */ -public abstract class ShapefileRecord -{ +public abstract class ShapefileRecord { + protected Shapefile shapeFile; protected int recordNumber; protected int contentLengthInBytes; @@ -52,39 +52,42 @@ public abstract class ShapefileRecord protected int numberOfParts; protected int numberOfPoints; protected int firstPartNumber; - /** Indicates if the record's point coordinates should be normalized. Defaults to false. */ + /** + * Indicates if the record's point coordinates should be normalized. + * Defaults to false. + */ protected boolean normalizePoints; protected static final int RECORD_HEADER_LENGTH = 8; protected static List measureTypes = new ArrayList(Arrays.asList( - Shapefile.SHAPE_POINT_M, Shapefile.SHAPE_POINT_Z, - Shapefile.SHAPE_MULTI_POINT_M, Shapefile.SHAPE_MULTI_POINT_Z, - Shapefile.SHAPE_POLYLINE_M, Shapefile.SHAPE_POLYLINE_Z, - Shapefile.SHAPE_POLYGON_M, Shapefile.SHAPE_POLYGON_Z + Shapefile.SHAPE_POINT_M, Shapefile.SHAPE_POINT_Z, + Shapefile.SHAPE_MULTI_POINT_M, Shapefile.SHAPE_MULTI_POINT_Z, + Shapefile.SHAPE_POLYLINE_M, Shapefile.SHAPE_POLYLINE_Z, + Shapefile.SHAPE_POLYGON_M, Shapefile.SHAPE_POLYGON_Z )); /** - * Constructs a record instance from the given {@link java.nio.ByteBuffer}. The buffer's current position must be - * the start of the record, and will be the start of the next record when the constructor returns. + * Constructs a record instance from the given {@link java.nio.ByteBuffer}. + * The buffer's current position must be the start of the record, and will + * be the start of the next record when the constructor returns. * * @param shapeFile the parent {@link Shapefile}. - * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read from. + * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read + * from. * - * @throws IllegalArgumentException if any argument is null or otherwise invalid. - * @throws gov.nasa.worldwind.exception.WWRuntimeException - * if the record's shape type does not match that of the shapefile. + * @throws IllegalArgumentException if any argument is null or otherwise + * invalid. + * @throws gov.nasa.worldwind.exception.WWRuntimeException if the record's + * shape type does not match that of the shapefile. */ - public ShapefileRecord(Shapefile shapeFile, ByteBuffer buffer) - { - if (shapeFile == null) - { + public ShapefileRecord(Shapefile shapeFile, ByteBuffer buffer) { + if (shapeFile == null) { String message = Logging.getMessage("nullValue.ShapefileIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (buffer == null) - { + if (buffer == null) { String message = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -92,12 +95,9 @@ public ShapefileRecord(Shapefile shapeFile, ByteBuffer buffer) // Save the buffer's current position. int pos = buffer.position(); - try - { + try { this.readFromBuffer(shapeFile, buffer); - } - finally - { + } finally { // Move to the end of the record. buffer.position(pos + this.contentLengthInBytes + RECORD_HEADER_LENGTH); } @@ -108,8 +108,7 @@ public ShapefileRecord(Shapefile shapeFile, ByteBuffer buffer) * * @return the shapefile containing this record. */ - public Shapefile getShapeFile() - { + public Shapefile getShapeFile() { return this.shapeFile; } @@ -118,18 +117,17 @@ public Shapefile getShapeFile() * * @return the record's ordinal position in the shapefile. */ - public int getRecordNumber() - { + public int getRecordNumber() { return this.recordNumber; } /** * Returns the record's shape type. * - * @return the record' shape type. See {@link Shapefile} for a list of the defined shape types. + * @return the record' shape type. See {@link Shapefile} for a list of the + * defined shape types. */ - public String getShapeType() - { + public String getShapeType() { return this.shapeType; } @@ -138,8 +136,7 @@ public String getShapeType() * * @return the record's attributes. */ - public DBaseRecord getAttributes() - { + public DBaseRecord getAttributes() { return this.attributes; } @@ -148,8 +145,7 @@ public DBaseRecord getAttributes() * * @param attributes the shapefile's attributes. May be null. */ - public void setAttributes(DBaseRecord attributes) - { + public void setAttributes(DBaseRecord attributes) { this.attributes = attributes; } @@ -158,8 +154,7 @@ public void setAttributes(DBaseRecord attributes) * * @return the number of parts in the record. */ - public int getNumberOfParts() - { + public int getNumberOfParts() { return this.numberOfParts; } @@ -168,8 +163,7 @@ public int getNumberOfParts() * * @return the first part number in the record. */ - public int getFirstPartNumber() - { + public int getFirstPartNumber() { return this.firstPartNumber; } @@ -178,8 +172,7 @@ public int getFirstPartNumber() * * @return the last part number in the record. */ - public int getLastPartNumber() - { + public int getLastPartNumber() { return this.firstPartNumber + this.numberOfParts - 1; } @@ -188,22 +181,20 @@ public int getLastPartNumber() * * @return the number of points in the record. */ - public int getNumberOfPoints() - { + public int getNumberOfPoints() { return this.numberOfPoints; } /** * Returns the number of points in a specified part of the record. * - * @param partNumber the part number for which to return the number of points. + * @param partNumber the part number for which to return the number of + * points. * * @return the number of points in the specified part. */ - public int getNumberOfPoints(int partNumber) - { - if (partNumber < 0 || partNumber >= this.getNumberOfParts()) - { + public int getNumberOfPoints(int partNumber) { + if (partNumber < 0 || partNumber >= this.getNumberOfParts()) { String message = Logging.getMessage("generic.indexOutOfRange", partNumber); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -214,17 +205,16 @@ public int getNumberOfPoints(int partNumber) } /** - * Returns the {@link gov.nasa.worldwind.util.VecBuffer} holding the X and Y points of a specified part. + * Returns the {@link gov.nasa.worldwind.util.VecBuffer} holding the X and Y + * points of a specified part. * * @param partNumber the part for which to return the point buffer. * - * @return the buffer holding the part's points. The points are ordered X0,Y0,X1,Y1,...Xn-1,Yn-1, where "n" is the - * number of points in the part. + * @return the buffer holding the part's points. The points are ordered + * X0,Y0,X1,Y1,...Xn-1,Yn-1, where "n" is the number of points in the part. */ - public VecBuffer getPointBuffer(int partNumber) - { - if (partNumber < 0 || partNumber >= this.getNumberOfParts()) - { + public VecBuffer getPointBuffer(int partNumber) { + if (partNumber < 0 || partNumber >= this.getNumberOfParts()) { String message = Logging.getMessage("generic.indexOutOfRange", partNumber); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -235,51 +225,56 @@ public VecBuffer getPointBuffer(int partNumber) } /** - * Returns the {@link gov.nasa.worldwind.util.CompoundVecBuffer} holding all the X and Y points for this record. The - * returned buffer contains one sub-buffer for each of this record's parts. The coordinates for each part are - * referenced by invoking {@link gov.nasa.worldwind.util.CompoundVecBuffer#subBuffer(int)}, where the index is one - * of this record's part IDs, starting with 0 and ending with {@link #getNumberOfParts()} - 1 - * (inclusive). + * Returns the {@link gov.nasa.worldwind.util.CompoundVecBuffer} holding all + * the X and Y points for this record. The returned buffer contains one + * sub-buffer for each of this record's parts. The coordinates for each part + * are referenced by invoking + * {@link gov.nasa.worldwind.util.CompoundVecBuffer#subBuffer(int)}, where + * the index is one of this record's part IDs, starting with 0 and ending + * with {@link #getNumberOfParts()} - 1 (inclusive). * * @return a CompoundVecBuffer that holds this record's coordinate data. */ - public CompoundVecBuffer getCompoundPointBuffer() - { + public CompoundVecBuffer getCompoundPointBuffer() { return this.getShapeFile().getPointBuffer().slice(this.getFirstPartNumber(), this.getLastPartNumber()); } /** - * Returns a four-element array containing this record's bounding rectangle, or null if this record has no bounding - * rectangle. + * Returns a four-element array containing this record's bounding rectangle, + * or null if this record has no bounding rectangle. *

      - * The returned array is ordered as follows: minimum Y, maximum Y, minimum X, and maximum X. If the Shapefile's - * coordinate system is geographic, the elements can be interpreted as angular degrees in the order minimum + * The returned array is ordered as follows: minimum Y, maximum Y, minimum + * X, and maximum X. If the Shapefile's coordinate system is geographic, the + * elements can be interpreted as angular degrees in the order minimum * latitude, maximum latitude, minimum longitude, and maximum longitude. * - * @return the record's bounding rectangle, or null to indicate that this record does not have a bounding - * rectangle. + * @return the record's bounding rectangle, or null to indicate that this + * record does not have a bounding rectangle. */ public abstract double[] getBoundingRectangle(); /** - * Reads and parses subclass-specific contents of a shapefile record from a specified buffer. The buffer's current - * position must be the start of the subclass' unique contents and will be the start of the next record when the - * constructor returns. + * Reads and parses subclass-specific contents of a shapefile record from a + * specified buffer. The buffer's current position must be the start of the + * subclass' unique contents and will be the start of the next record when + * the constructor returns. * * @param shapefile the containing {@link Shapefile}. - * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read from. + * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read + * from. */ protected abstract void doReadFromBuffer(Shapefile shapefile, ByteBuffer buffer); /** - * Reads and parses the contents of a shapefile record from a specified buffer. The buffer's current position must - * be the start of the record and will be the start of the next record when the constructor returns. + * Reads and parses the contents of a shapefile record from a specified + * buffer. The buffer's current position must be the start of the record and + * will be the start of the next record when the constructor returns. * * @param shapefile the containing {@link Shapefile}. - * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read from. + * @param buffer the shapefile record {@link java.nio.ByteBuffer} to read + * from. */ - protected void readFromBuffer(Shapefile shapefile, ByteBuffer buffer) - { + protected void readFromBuffer(Shapefile shapefile, ByteBuffer buffer) { // Read record number and record length - big endian. buffer.order(ByteOrder.BIG_ENDIAN); this.recordNumber = buffer.getInt(); @@ -298,31 +293,31 @@ protected void readFromBuffer(Shapefile shapefile, ByteBuffer buffer) } /** - * Verifies that the record's shape type matches the expected one, typically that of the shapefile. All non-null - * records in a Shapefile must be of the same type. Throws an exception if the types do not match and the shape type - * is not {@link Shapefile#SHAPE_NULL}. Records of type SHAPE_NULL are always valid, and - * may appear in any Shapefile. + * Verifies that the record's shape type matches the expected one, typically + * that of the shapefile. All non-null records in a Shapefile must be of the + * same type. Throws an exception if the types do not match and the shape + * type is not {@link Shapefile#SHAPE_NULL}. Records of type + * SHAPE_NULL are always valid, and may appear in any + * Shapefile. *

      - * For details, see the ESRI Shapefile specification at , + * For details, see the ESRI Shapefile specification at + * , * pages 4 and 5. * * @param shapefile the shapefile. * @param shapeType the record's shape type. * - * @throws WWRuntimeException if the shape types do not match. + * @throws WWRuntimeException if the shape types do not match. * @throws IllegalArgumentException if the specified shape type is null. */ - protected void validateShapeType(Shapefile shapefile, String shapeType) - { - if (shapeType == null) - { + protected void validateShapeType(Shapefile shapefile, String shapeType) { + if (shapeType == null) { String message = Logging.getMessage("nullValue.ShapeType"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (!shapeType.equals(shapefile.getShapeType()) && !shapeType.equals(Shapefile.SHAPE_NULL)) - { + if (!shapeType.equals(shapefile.getShapeType()) && !shapeType.equals(Shapefile.SHAPE_NULL)) { String message = Logging.getMessage("SHP.UnsupportedShapeType", shapeType); Logging.logger().severe(message); throw new WWRuntimeException(message); @@ -330,13 +325,13 @@ protected void validateShapeType(Shapefile shapefile, String shapeType) } /** - * Indicates whether the record is a shape type capable of containing optional measure values. Does not indicate - * whether the record actually contains measure values. + * Indicates whether the record is a shape type capable of containing + * optional measure values. Does not indicate whether the record actually + * contains measure values. * * @return true if the record may contain measure values. */ - protected boolean isMeasureType() - { + protected boolean isMeasureType() { return Shapefile.isMeasureType(this.getShapeType()); } @@ -345,146 +340,141 @@ protected boolean isMeasureType() * * @return true if the record is a type containing Z values. */ - protected boolean isZType() - { + protected boolean isZType() { return Shapefile.isZType(this.getShapeType()); } /** - * Indicates whether this is a null record. When true, this record may be cast to a ShapefileRecordNull by calling - * {@link #asNullRecord()}. + * Indicates whether this is a null record. When true, this record may be + * cast to a ShapefileRecordNull by calling {@link #asNullRecord()}. * * @return true if this is a null record, otherwise false. */ - public boolean isNullRecord() - { + public boolean isNullRecord() { return false; } /** - * Indicates whether this is a point record. When true, this record may be cast to a ShapefileRecordPoint by calling - * {@link #asPointRecord()}. + * Indicates whether this is a point record. When true, this record may be + * cast to a ShapefileRecordPoint by calling {@link #asPointRecord()}. * * @return true if this is a point record, otherwise false. */ - public boolean isPointRecord() - { + public boolean isPointRecord() { return false; } /** - * Indicates whether this is a multi point record. When true, this record may be cast to a ShapefileRecordMultiPoint - * by calling {@link #asPointRecord()}. + * Indicates whether this is a multi point record. When true, this record + * may be cast to a ShapefileRecordMultiPoint by calling + * {@link #asPointRecord()}. * * @return true if this is a multi point record, otherwise false. */ - public boolean isMultiPointRecord() - { + public boolean isMultiPointRecord() { return false; } /** - * Indicates whether this is a polyline record. When true, this record may be cast to a ShapefileRecordPolyline by - * calling {@link #asPolylineRecord()}. + * Indicates whether this is a polyline record. When true, this record may + * be cast to a ShapefileRecordPolyline by calling + * {@link #asPolylineRecord()}. * * @return true if this is a polyline record, otherwise false. */ - public boolean isPolylineRecord() - { + public boolean isPolylineRecord() { return false; } /** - * Indicates whether this is a polygon record. When true, this record may be cast to a ShapefileRecordPolygon by - * calling {@link #asPolygonRecord()}. + * Indicates whether this is a polygon record. When true, this record may be + * cast to a ShapefileRecordPolygon by calling {@link #asPolygonRecord()}. * * @return true if this is a polygon record, otherwise false. */ - public boolean isPolygonRecord() - { + public boolean isPolygonRecord() { return false; } /** - * Returns this record as a ShapefileRecordNull. This results in a class cast exception if this is not a null - * record. Check this record's type using {@link #isNullRecord()} prior to calling this method. + * Returns this record as a ShapefileRecordNull. This results in a class + * cast exception if this is not a null record. Check this record's type + * using {@link #isNullRecord()} prior to calling this method. * * @return this record cast as a ShapefileRecordNull. */ - public ShapefileRecordNull asNullRecord() - { + public ShapefileRecordNull asNullRecord() { return (ShapefileRecordNull) this; } /** - * Returns this record as a ShapefileRecordPoint. This results in a class cast exception if this is not a point - * record. Check this record's type using {@link #isPointRecord()} prior to calling this method. + * Returns this record as a ShapefileRecordPoint. This results in a class + * cast exception if this is not a point record. Check this record's type + * using {@link #isPointRecord()} prior to calling this method. * * @return this record cast as a ShapefileRecordPoint. */ - public ShapefileRecordPoint asPointRecord() - { + public ShapefileRecordPoint asPointRecord() { return (ShapefileRecordPoint) this; } /** - * Returns this record as a ShapefileRecordMultiPoint. This results in a class cast exception if this is not a multi - * point record. Check this record's type using {@link #isMultiPointRecord()} prior to calling this method. + * Returns this record as a ShapefileRecordMultiPoint. This results in a + * class cast exception if this is not a multi point record. Check this + * record's type using {@link #isMultiPointRecord()} prior to calling this + * method. * * @return this record cast as a ShapefileRecordMultiPoint. */ - public ShapefileRecordMultiPoint asMultiPointRecord() - { + public ShapefileRecordMultiPoint asMultiPointRecord() { return (ShapefileRecordMultiPoint) this; } /** - * Returns this record as a ShapefileRecordPolyline. This results in a class cast exception if this is not a - * polyline record. Check this record's type using {@link #isPolylineRecord()} prior to calling this method. + * Returns this record as a ShapefileRecordPolyline. This results in a class + * cast exception if this is not a polyline record. Check this record's type + * using {@link #isPolylineRecord()} prior to calling this method. * * @return this record cast as a ShapefileRecordPolyline. */ - public ShapefileRecordPolyline asPolylineRecord() - { + public ShapefileRecordPolyline asPolylineRecord() { return (ShapefileRecordPolyline) this; } /** - * Returns this record as a ShapefileRecordPolygon. This results in a class cast exception if this is not a polygon - * record. Check this record's type using {@link #isPolygonRecord()} prior to calling this method. + * Returns this record as a ShapefileRecordPolygon. This results in a class + * cast exception if this is not a polygon record. Check this record's type + * using {@link #isPolygonRecord()} prior to calling this method. * * @return this record cast as a ShapefileRecordPolygon. */ - public ShapefileRecordPolygon asPolygonRecord() - { + public ShapefileRecordPolygon asPolygonRecord() { return (ShapefileRecordPolygon) this; } /** * Returns whether the record's point coordinates should be normalized. * - * @return true if the record's points should be normalized; false otherwise. + * @return true if the record's points should be normalized; + * false otherwise. */ - public boolean isNormalizePoints() - { + public boolean isNormalizePoints() { return this.normalizePoints; } /** - * Specifies if the record's point coordinates should be normalized. Defaults to false. + * Specifies if the record's point coordinates should be normalized. + * Defaults to false. * - * @param normalizePoints true if the record's points should be normalized; false - * otherwise. + * @param normalizePoints true if the record's points should be + * normalized; false otherwise. */ - public void setNormalizePoints(boolean normalizePoints) - { + public void setNormalizePoints(boolean normalizePoints) { this.normalizePoints = normalizePoints; } - public void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException - { - if (xmlWriter == null) - { + public void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException { + if (xmlWriter == null) { String message = Logging.getMessage("Export.UnsupportedOutputObject"); Logging.logger().warning(message); throw new IllegalArgumentException(message); @@ -498,8 +488,7 @@ public void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStream xmlWriter.writeAttribute("points", Integer.toString(this.getNumberOfPoints())); xmlWriter.writeCharacters("\n"); - for (Map.Entry a : this.getAttributes().getEntries()) - { + for (Map.Entry a : this.getAttributes().getEntries()) { xmlWriter.writeStartElement("Attribute"); xmlWriter.writeAttribute("name", a.getKey() != null ? a.getKey().toString() : ""); @@ -509,11 +498,9 @@ public void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStream xmlWriter.writeCharacters("\n"); } - if (this.getNumberOfParts() > 0) - { + if (this.getNumberOfParts() > 0) { VecBuffer vb = this.getPointBuffer(0); - for (LatLon ll : vb.getLocations()) - { + for (LatLon ll : vb.getLocations()) { xmlWriter.writeStartElement("Point"); xmlWriter.writeAttribute("x", Double.toString(ll.getLatitude().degrees)); xmlWriter.writeAttribute("y", Double.toString(ll.getLongitude().degrees)); @@ -523,49 +510,47 @@ public void exportAsXML(XMLStreamWriter xmlWriter) throws IOException, XMLStream } // TODO: export record-type specific fields - xmlWriter.writeEndElement(); // Record } /** - * Export the record as KML. This implementation does nothing; subclasses may override this method to provide KML - * export. + * Export the record as KML. This implementation does nothing; subclasses + * may override this method to provide KML export. * * @param xmlWriter Writer to receive KML. * - * @throws IOException If an exception occurs while writing the KML - * @throws XMLStreamException If an exception occurs while exporting the data. + * @throws IOException If an exception occurs while writing the KML + * @throws XMLStreamException If an exception occurs while exporting the + * data. */ - public void exportAsKML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException - { + public void exportAsKML(XMLStreamWriter xmlWriter) throws IOException, XMLStreamException { } - public void printInfo(boolean printCoordinates) - { + public void printInfo(boolean printCoordinates) { System.out.printf("%d, %s: %d parts, %d points", this.getRecordNumber(), this.getShapeType(), - this.getNumberOfParts(), this.getNumberOfPoints()); - for (Map.Entry a : this.getAttributes().getEntries()) - { - if (a.getKey() != null) + this.getNumberOfParts(), this.getNumberOfPoints()); + for (Map.Entry a : this.getAttributes().getEntries()) { + if (a.getKey() != null) { System.out.printf(", %s", a.getKey()); - if (a.getValue() != null) + } + if (a.getValue() != null) { System.out.printf(", %s", a.getValue()); + } } System.out.println(); System.out.print("\tAttributes: "); - for (Map.Entry entry : this.getAttributes().getEntries()) - { + for (Map.Entry entry : this.getAttributes().getEntries()) { System.out.printf("%s = %s, ", entry.getKey(), entry.getValue()); } System.out.println(); - if (!printCoordinates) + if (!printCoordinates) { return; + } VecBuffer vb = this.getPointBuffer(0); - for (LatLon ll : vb.getLocations()) - { + for (LatLon ll : vb.getLocations()) { System.out.printf("\t%f, %f\n", ll.getLatitude().degrees, ll.getLongitude().degrees); } } diff --git a/src/gov/nasa/worldwind/geom/Sector.java b/src/gov/nasa/worldwind/geom/Sector.java index 6a5d1fd584..5b1e73092c 100644 --- a/src/gov/nasa/worldwind/geom/Sector.java +++ b/src/gov/nasa/worldwind/geom/Sector.java @@ -39,20 +39,28 @@ import java.util.*; /** - * Sector represents a rectangular region of latitude and longitude. The region is defined by four angles: - * its minimum and maximum latitude, its minimum and maximum longitude. The angles are assumed to be normalized to +/- - * 90 degrees latitude and +/- 180 degrees longitude. The minimums and maximums are relative to these ranges, e.g., -80 - * is less than 20. Behavior of the class is undefined for angles outside these ranges. Normalization is not performed - * on the angles by this class, nor is it verified by the class' methods. See {@link Angle} for a description of - * specifying angles.

      Sector instances are immutable.

      + * Sector represents a rectangular region of latitude and + * longitude. The region is defined by four angles: its minimum and maximum + * latitude, its minimum and maximum longitude. The angles are assumed to be + * normalized to +/- 90 degrees latitude and +/- 180 degrees longitude. The + * minimums and maximums are relative to these ranges, e.g., -80 is less than + * 20. Behavior of the class is undefined for angles outside these ranges. + * Normalization is not performed on the angles by this class, nor is it + * verified by the class' methods. See {@link Angle} for a description of + * specifying angles. + *

      + * Sector instances are immutable.

      * * @author Tom Gaskins * @version $Id: Sector.java 2397 2014-10-28 17:13:04Z dcollins $ * @see Angle */ -public class Sector implements Cacheable, Comparable, Iterable -{ - /** A Sector of latitude [-90 degrees, + 90 degrees] and longitude [-180 degrees, + 180 degrees]. */ +public class Sector implements Cacheable, Comparable, Iterable { + + /** + * A Sector of latitude [-90 degrees, + 90 degrees] and + * longitude [-180 degrees, + 180 degrees]. + */ public static final Sector FULL_SPHERE = new Sector(Angle.NEG90, Angle.POS90, Angle.NEG180, Angle.POS180); public static final Sector EMPTY_SECTOR = new Sector(Angle.ZERO, Angle.ZERO, Angle.ZERO, Angle.ZERO); @@ -64,73 +72,79 @@ public class Sector implements Cacheable, Comparable, Iterable private final Angle deltaLon; /** - * Creates a new Sector and initializes it to the specified angles. The angles are assumed to be - * normalized to +/- 90 degrees latitude and +/- 180 degrees longitude, but this method does not verify that. + * Creates a new Sector and initializes it to the specified + * angles. The angles are assumed to be normalized to +/- 90 degrees + * latitude and +/- 180 degrees longitude, but this method does not verify + * that. * - * @param minLatitude the sector's minimum latitude in degrees. - * @param maxLatitude the sector's maximum latitude in degrees. + * @param minLatitude the sector's minimum latitude in degrees. + * @param maxLatitude the sector's maximum latitude in degrees. * @param minLongitude the sector's minimum longitude in degrees. * @param maxLongitude the sector's maximum longitude in degrees. * * @return the new Sector */ public static Sector fromDegrees(double minLatitude, double maxLatitude, double minLongitude, - double maxLongitude) - { + double maxLongitude) { return new Sector(Angle.fromDegrees(minLatitude), Angle.fromDegrees(maxLatitude), Angle.fromDegrees( - minLongitude), Angle.fromDegrees(maxLongitude)); + minLongitude), Angle.fromDegrees(maxLongitude)); } /** - * Creates a new Sector and initializes it to the specified angles. The angles are assumed to be - * normalized to +/- 90 degrees latitude and +/- 180 degrees longitude, but this method does not verify that. + * Creates a new Sector and initializes it to the specified + * angles. The angles are assumed to be normalized to +/- 90 degrees + * latitude and +/- 180 degrees longitude, but this method does not verify + * that. * - * @param minLatitude the sector's minimum latitude in degrees. - * @param maxLatitude the sector's maximum latitude in degrees. + * @param minLatitude the sector's minimum latitude in degrees. + * @param maxLatitude the sector's maximum latitude in degrees. * @param minLongitude the sector's minimum longitude in degrees. * @param maxLongitude the sector's maximum longitude in degrees. * * @return the new Sector */ public static Sector fromDegreesAndClamp(double minLatitude, double maxLatitude, double minLongitude, - double maxLongitude) - { - if (minLatitude < -90) + double maxLongitude) { + if (minLatitude < -90) { minLatitude = -90; - if (maxLatitude > 90) + } + if (maxLatitude > 90) { maxLatitude = 90; - if (minLongitude < -180) + } + if (minLongitude < -180) { minLongitude = -180; - if (maxLongitude > 180) + } + if (maxLongitude > 180) { maxLongitude = 180; + } return new Sector(Angle.fromDegrees(minLatitude), Angle.fromDegrees(maxLatitude), Angle.fromDegrees( - minLongitude), Angle.fromDegrees(maxLongitude)); + minLongitude), Angle.fromDegrees(maxLongitude)); } /** - * Creates a new Sector and initializes it to angles in the specified array. The array is assumed to - * hold four elements containing the Sector's angles, and must be ordered as follows: minimum latitude, maximum - * latitude, minimum longitude, and maximum longitude. Additionally, the angles are assumed to be normalized to +/- - * 90 degrees latitude and +/- 180 degrees longitude, but this method does not verify that. + * Creates a new Sector and initializes it to angles in the + * specified array. The array is assumed to hold four elements containing + * the Sector's angles, and must be ordered as follows: minimum latitude, + * maximum latitude, minimum longitude, and maximum longitude. Additionally, + * the angles are assumed to be normalized to +/- 90 degrees latitude and + * +/- 180 degrees longitude, but this method does not verify that. * * @param array the array of angles in degrees. * * @return he new Sector * - * @throws IllegalArgumentException if array is null or if its length is less than 4. + * @throws IllegalArgumentException if array is null or if its + * length is less than 4. */ - public static Sector fromDegrees(double[] array) - { - if (array == null) - { + public static Sector fromDegrees(double[] array) { + if (array == null) { String message = Logging.getMessage("nullValue.ArrayIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (array.length < 4) - { + if (array.length < 4) { String message = Logging.getMessage("generic.ArrayInvalidLength", array.length); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -140,69 +154,70 @@ public static Sector fromDegrees(double[] array) } /** - * Creates a new Sector and initializes it to the angles resulting from the given {@link - * java.awt.geom.Rectangle2D} in degrees lat-lon coordinates where x corresponds to longitude and y to latitude. The - * resulting geographic angles are assumed to be normalized to +/- 90 degrees latitude and +/- 180 degrees - * longitude, but this method does not verify that. + * Creates a new Sector and initializes it to the angles + * resulting from the given {@link + * java.awt.geom.Rectangle2D} in degrees lat-lon coordinates where x + * corresponds to longitude and y to latitude. The resulting geographic + * angles are assumed to be normalized to +/- 90 degrees latitude and +/- + * 180 degrees longitude, but this method does not verify that. * * @param rectangle the sector's rectangle in degrees lat-lon coordinates. * * @return the new Sector */ - public static Sector fromDegrees(java.awt.geom.Rectangle2D rectangle) - { + public static Sector fromDegrees(java.awt.geom.Rectangle2D rectangle) { return fromDegrees(rectangle.getY(), rectangle.getMaxY(), rectangle.getX(), rectangle.getMaxX()); } /** - * Creates a new Sector and initializes it to the specified angles. The angles are assumed to be - * normalized to +/- \u03c0/2 radians latitude and +/- \u03c0 radians longitude, but this method does not verify - * that. + * Creates a new Sector and initializes it to the specified + * angles. The angles are assumed to be normalized to +/- \u03c0/2 radians + * latitude and +/- \u03c0 radians longitude, but this method does not + * verify that. * - * @param minLatitude the sector's minimum latitude in radians. - * @param maxLatitude the sector's maximum latitude in radians. + * @param minLatitude the sector's minimum latitude in radians. + * @param maxLatitude the sector's maximum latitude in radians. * @param minLongitude the sector's minimum longitude in radians. * @param maxLongitude the sector's maximum longitude in radians. * * @return the new Sector */ public static Sector fromRadians(double minLatitude, double maxLatitude, double minLongitude, - double maxLongitude) - { + double maxLongitude) { return new Sector(Angle.fromRadians(minLatitude), Angle.fromRadians(maxLatitude), Angle.fromRadians( - minLongitude), Angle.fromRadians(maxLongitude)); + minLongitude), Angle.fromRadians(maxLongitude)); } /** - * Returns a geographic Sector which bounds the specified UTM rectangle. The UTM rectangle is located in specified - * UTM zone and hemisphere. + * Returns a geographic Sector which bounds the specified UTM rectangle. The + * UTM rectangle is located in specified UTM zone and hemisphere. * - * @param zone the UTM zone. - * @param hemisphere the UTM hemisphere, either {@link gov.nasa.worldwind.avlist.AVKey#NORTH} or {@link + * @param zone the UTM zone. + * @param hemisphere the UTM hemisphere, either + * {@link gov.nasa.worldwind.avlist.AVKey#NORTH} or {@link * gov.nasa.worldwind.avlist.AVKey#SOUTH}. - * @param minEasting the minimum UTM easting, in meters. - * @param maxEasting the maximum UTM easting, in meters. + * @param minEasting the minimum UTM easting, in meters. + * @param maxEasting the maximum UTM easting, in meters. * @param minNorthing the minimum UTM northing, in meters. * @param maxNorthing the maximum UTM northing, in meters. * * @return a Sector that bounds the specified UTM rectangle. * - * @throws IllegalArgumentException if zone is outside the range 1-60, if hemisphere is - * null, or if hemisphere is not one of {@link - * gov.nasa.worldwind.avlist.AVKey#NORTH} or {@link gov.nasa.worldwind.avlist.AVKey#SOUTH}. + * @throws IllegalArgumentException if zone is outside the + * range 1-60, if hemisphere is null, or if + * hemisphere is not one of {@link + * gov.nasa.worldwind.avlist.AVKey#NORTH} or + * {@link gov.nasa.worldwind.avlist.AVKey#SOUTH}. */ public static Sector fromUTMRectangle(int zone, String hemisphere, double minEasting, double maxEasting, - double minNorthing, double maxNorthing) - { - if (zone < 1 || zone > 60) - { + double minNorthing, double maxNorthing) { + if (zone < 1 || zone > 60) { String message = Logging.getMessage("generic.ZoneIsInvalid", zone); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (!AVKey.NORTH.equals(hemisphere) && !AVKey.SOUTH.equals(hemisphere)) - { + if (!AVKey.NORTH.equals(hemisphere) && !AVKey.SOUTH.equals(hemisphere)) { String message = Logging.getMessage("generic.HemisphereIsInvalid", hemisphere); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -216,17 +231,16 @@ public static Sector fromUTMRectangle(int zone, String hemisphere, double minEas return boundingSector(Arrays.asList(ll, lr, ur, ul)); } - public static Sector boundingSector(java.util.Iterator positions) - { - if (positions == null) - { + public static Sector boundingSector(java.util.Iterator positions) { + if (positions == null) { String message = Logging.getMessage("nullValue.TracksPointsIteratorNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (!positions.hasNext()) + if (!positions.hasNext()) { return EMPTY_SECTOR; + } TrackPoint position = positions.next(); double minLat = position.getLatitude(); @@ -234,71 +248,72 @@ public static Sector boundingSector(java.util.Iterator positions) double maxLat = minLat; double maxLon = minLon; - while (positions.hasNext()) - { + while (positions.hasNext()) { TrackPoint p = positions.next(); double lat = p.getLatitude(); - if (lat < minLat) + if (lat < minLat) { minLat = lat; - else if (lat > maxLat) + } else if (lat > maxLat) { maxLat = lat; + } double lon = p.getLongitude(); - if (lon < minLon) + if (lon < minLon) { minLon = lon; - else if (lon > maxLon) + } else if (lon > maxLon) { maxLon = lon; + } } return Sector.fromDegrees(minLat, maxLat, minLon, maxLon); } - public static Sector boundingSector(Iterable locations) - { - if (locations == null) - { + public static Sector boundingSector(Iterable locations) { + if (locations == null) { String message = Logging.getMessage("nullValue.PositionsListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (!locations.iterator().hasNext()) + if (!locations.iterator().hasNext()) { return EMPTY_SECTOR; // TODO: should be returning null - + } double minLat = Angle.POS90.getDegrees(); double minLon = Angle.POS180.getDegrees(); double maxLat = Angle.NEG90.getDegrees(); double maxLon = Angle.NEG180.getDegrees(); - for (LatLon p : locations) - { + for (LatLon p : locations) { double lat = p.getLatitude().getDegrees(); - if (lat < minLat) + if (lat < minLat) { minLat = lat; - if (lat > maxLat) + } + if (lat > maxLat) { maxLat = lat; + } double lon = p.getLongitude().getDegrees(); - if (lon < minLon) + if (lon < minLon) { minLon = lon; - if (lon > maxLon) + } + if (lon > maxLon) { maxLon = lon; + } } return Sector.fromDegrees(minLat, maxLat, minLon, maxLon); } - public static Sector[] splitBoundingSectors(Iterable locations) - { - if (locations == null) - { + public static Sector[] splitBoundingSectors(Iterable locations) { + if (locations == null) { String message = Logging.getMessage("nullValue.LocationInListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (!locations.iterator().hasNext()) + if (!locations.iterator().hasNext()) { return null; + } double minLat = Angle.POS90.getDegrees(); double minLon = Angle.POS180.getDegrees(); @@ -307,27 +322,27 @@ public static Sector[] splitBoundingSectors(Iterable locations LatLon lastLocation = null; - for (LatLon ll : locations) - { + for (LatLon ll : locations) { double lat = ll.getLatitude().getDegrees(); - if (lat < minLat) + if (lat < minLat) { minLat = lat; - if (lat > maxLat) + } + if (lat > maxLat) { maxLat = lat; + } double lon = ll.getLongitude().getDegrees(); - if (lon >= 0 && lon < minLon) + if (lon >= 0 && lon < minLon) { minLon = lon; - if (lon <= 0 && lon > maxLon) + } + if (lon <= 0 && lon > maxLon) { maxLon = lon; + } - if (lastLocation != null) - { + if (lastLocation != null) { double lastLon = lastLocation.getLongitude().getDegrees(); - if (Math.signum(lon) != Math.signum(lastLon)) - { - if (Math.abs(lon - lastLon) < 180) - { + if (Math.signum(lon) != Math.signum(lastLon)) { + if (Math.abs(lon - lastLon) < 180) { // Crossing the zero longitude line too maxLon = 0; minLon = 0; @@ -337,20 +352,18 @@ public static Sector[] splitBoundingSectors(Iterable locations lastLocation = ll; } - if (minLat == maxLat && minLon == maxLon) + if (minLat == maxLat && minLon == maxLon) { return null; + } - return new Sector[] - { - Sector.fromDegrees(minLat, maxLat, minLon, 180), // Sector on eastern hemisphere. - Sector.fromDegrees(minLat, maxLat, -180, maxLon) // Sector on western hemisphere. - }; + return new Sector[]{ + Sector.fromDegrees(minLat, maxLat, minLon, 180), // Sector on eastern hemisphere. + Sector.fromDegrees(minLat, maxLat, -180, maxLon) // Sector on western hemisphere. + }; } - public static Sector boundingSector(LatLon pA, LatLon pB) - { - if (pA == null || pB == null) - { + public static Sector boundingSector(LatLon pA, LatLon pB) { + if (pA == null || pB == null) { String message = Logging.getMessage("nullValue.PositionsListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -361,75 +374,75 @@ public static Sector boundingSector(LatLon pA, LatLon pB) double maxLat = pA.getLatitude().degrees; double maxLon = pA.getLongitude().degrees; - if (pB.getLatitude().degrees < minLat) + if (pB.getLatitude().degrees < minLat) { minLat = pB.getLatitude().degrees; - else if (pB.getLatitude().degrees > maxLat) + } else if (pB.getLatitude().degrees > maxLat) { maxLat = pB.getLatitude().degrees; + } - if (pB.getLongitude().degrees < minLon) + if (pB.getLongitude().degrees < minLon) { minLon = pB.getLongitude().degrees; - else if (pB.getLongitude().degrees > maxLon) + } else if (pB.getLongitude().degrees > maxLon) { maxLon = pB.getLongitude().degrees; + } return Sector.fromDegrees(minLat, maxLat, minLon, maxLon); } /** - * Returns a new Sector encompassing a circle centered at a given position, with a given radius in - * meter. + * Returns a new Sector encompassing a circle centered at a + * given position, with a given radius in meter. * - * @param globe a Globe instance. + * @param globe a Globe instance. * @param center the circle center position. * @param radius the circle radius in meter. * * @return the circle bounding sector. */ - public static Sector boundingSector(Globe globe, LatLon center, double radius) - { + public static Sector boundingSector(Globe globe, LatLon center, double radius) { double halfDeltaLatRadians = radius / globe.getRadiusAt(center); double halfDeltaLonRadians = Math.PI * 2; - if (center.getLatitude().cos() > 0) + if (center.getLatitude().cos() > 0) { halfDeltaLonRadians = halfDeltaLatRadians / center.getLatitude().cos(); + } return new Sector( - Angle.fromRadiansLatitude(center.getLatitude().radians - halfDeltaLatRadians), - Angle.fromRadiansLatitude(center.getLatitude().radians + halfDeltaLatRadians), - Angle.fromRadiansLongitude(center.getLongitude().radians - halfDeltaLonRadians), - Angle.fromRadiansLongitude(center.getLongitude().radians + halfDeltaLonRadians)); + Angle.fromRadiansLatitude(center.getLatitude().radians - halfDeltaLatRadians), + Angle.fromRadiansLatitude(center.getLatitude().radians + halfDeltaLatRadians), + Angle.fromRadiansLongitude(center.getLongitude().radians - halfDeltaLonRadians), + Angle.fromRadiansLongitude(center.getLongitude().radians + halfDeltaLonRadians)); } /** - * Returns an array of Sectors encompassing a circle centered at a given position, with a given radius in meters. If - * the geometry defined by the circle and radius spans the international dateline, this will return two sectors, one - * for each side of the dateline. Otherwise, this will return a single bounding sector. This returns null if the - * radius is zero. + * Returns an array of Sectors encompassing a circle centered at a given + * position, with a given radius in meters. If the geometry defined by the + * circle and radius spans the international dateline, this will return two + * sectors, one for each side of the dateline. Otherwise, this will return a + * single bounding sector. This returns null if the radius is zero. * - * @param globe a Globe instance. + * @param globe a Globe instance. * @param center the circle center location. * @param radius the circle radius in meters. * * @return the circle's bounding sectors, or null if the radius is zero. * - * @throws IllegalArgumentException if either the globe or center is null, or if the radius is less than zero. + * @throws IllegalArgumentException if either the globe or center is null, + * or if the radius is less than zero. */ - public static Sector[] splitBoundingSectors(Globe globe, LatLon center, double radius) - { - if (globe == null) - { + public static Sector[] splitBoundingSectors(Globe globe, LatLon center, double radius) { + if (globe == null) { String message = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (center == null) - { + if (center == null) { String message = Logging.getMessage("nullValue.CenterIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (radius < 0) - { + if (radius < 0) { String message = Logging.getMessage("generic.ArgumentOutOfRange", "radius < 0"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -444,8 +457,7 @@ public static Sector[] splitBoundingSectors(Globe globe, LatLon center, double r double maxLon; // If the circle does not cross a pole, then compute the max and min longitude. - if (minLat >= Angle.NEG90.radians && maxLat <= Angle.POS90.radians) - { + if (minLat >= Angle.NEG90.radians && maxLat <= Angle.POS90.radians) { // We want to find the maximum and minimum longitude values on the circle. We will start with equation 5-6 // from "Map Projections - A Working Manual", page 31, and solve for the value of Az that will maximize // lon - lon0. @@ -477,59 +489,56 @@ public static Sector[] splitBoundingSectors(Globe globe, LatLon center, double r // circle would cover a pole. double az; if (Math.abs(Angle.POS90.radians - halfDeltaLatRadians) - > 0.001) // Consider within 1/1000th of a radian to be equal + > 0.001) // Consider within 1/1000th of a radian to be equal + { az = Math.acos(Math.tan(halfDeltaLatRadians) * Math.tan(center.latitude.radians)); - else + } else { az = Angle.POS90.radians; + } LatLon east = LatLon.greatCircleEndPosition(center, az, halfDeltaLatRadians); LatLon west = LatLon.greatCircleEndPosition(center, -az, halfDeltaLatRadians); minLon = Math.min(east.longitude.radians, west.longitude.radians); maxLon = Math.max(east.longitude.radians, west.longitude.radians); - } - else - { + } else { // If the circle crosses the pole then it spans the full circle of longitude minLon = Angle.NEG180.radians; maxLon = Angle.POS180.radians; } LatLon ll = new LatLon( - Angle.fromRadiansLatitude(minLat), - Angle.normalizedLongitude(Angle.fromRadians(minLon))); + Angle.fromRadiansLatitude(minLat), + Angle.normalizedLongitude(Angle.fromRadians(minLon))); LatLon ur = new LatLon( - Angle.fromRadiansLatitude(maxLat), - Angle.normalizedLongitude(Angle.fromRadians(maxLon))); + Angle.fromRadiansLatitude(maxLat), + Angle.normalizedLongitude(Angle.fromRadians(maxLon))); Iterable locations = java.util.Arrays.asList(ll, ur); - if (LatLon.locationsCrossDateLine(locations)) - { + if (LatLon.locationsCrossDateLine(locations)) { return splitBoundingSectors(locations); - } - else - { + } else { Sector s = boundingSector(locations); - return (s != null && !s.equals(Sector.EMPTY_SECTOR)) ? new Sector[] {s} : null; + return (s != null && !s.equals(Sector.EMPTY_SECTOR)) ? new Sector[]{s} : null; } } /** - * Creates a new Sector and initializes it to the specified angles. The angles are assumed to be - * normalized to +/- 90 degrees latitude and +/- 180 degrees longitude, but this method does not verify that. + * Creates a new Sector and initializes it to the specified + * angles. The angles are assumed to be normalized to +/- 90 degrees + * latitude and +/- 180 degrees longitude, but this method does not verify + * that. * - * @param minLatitude the sector's minimum latitude. - * @param maxLatitude the sector's maximum latitude. + * @param minLatitude the sector's minimum latitude. + * @param maxLatitude the sector's maximum latitude. * @param minLongitude the sector's minimum longitude. * @param maxLongitude the sector's maximum longitude. * * @throws IllegalArgumentException if any of the angles are null */ - public Sector(Angle minLatitude, Angle maxLatitude, Angle minLongitude, Angle maxLongitude) - { - if (minLatitude == null || maxLatitude == null || minLongitude == null || maxLongitude == null) - { + public Sector(Angle minLatitude, Angle maxLatitude, Angle minLongitude, Angle maxLongitude) { + if (minLatitude == null || maxLatitude == null || minLongitude == null || maxLongitude == null) { String message = Logging.getMessage("nullValue.InputAnglesNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -543,10 +552,8 @@ public Sector(Angle minLatitude, Angle maxLatitude, Angle minLongitude, Angle ma this.deltaLon = Angle.fromDegrees(this.maxLongitude.degrees - this.minLongitude.degrees); } - public Sector(Sector sector) - { - if (sector == null) - { + public Sector(Sector sector) { + if (sector == null) { String message = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -565,8 +572,7 @@ public Sector(Sector sector) * * @return The sector's minimum latitude. */ - public final Angle getMinLatitude() - { + public final Angle getMinLatitude() { return minLatitude; } @@ -575,8 +581,7 @@ public final Angle getMinLatitude() * * @return The sector's minimum longitude. */ - public final Angle getMinLongitude() - { + public final Angle getMinLongitude() { return minLongitude; } @@ -585,8 +590,7 @@ public final Angle getMinLongitude() * * @return The sector's maximum latitude. */ - public final Angle getMaxLatitude() - { + public final Angle getMaxLatitude() { return maxLatitude; } @@ -595,68 +599,63 @@ public final Angle getMaxLatitude() * * @return The sector's maximum longitude. */ - public final Angle getMaxLongitude() - { + public final Angle getMaxLongitude() { return maxLongitude; } /** - * Returns the angular difference between the sector's minimum and maximum latitudes: max - min + * Returns the angular difference between the sector's minimum and maximum + * latitudes: max - min * - * @return The angular difference between the sector's minimum and maximum latitudes. + * @return The angular difference between the sector's minimum and maximum + * latitudes. */ - public final Angle getDeltaLat() - { + public final Angle getDeltaLat() { return this.deltaLat;//Angle.fromDegrees(this.maxLatitude.degrees - this.minLatitude.degrees); } - public final double getDeltaLatDegrees() - { + public final double getDeltaLatDegrees() { return this.deltaLat.degrees;//this.maxLatitude.degrees - this.minLatitude.degrees; } - public final double getDeltaLatRadians() - { + public final double getDeltaLatRadians() { return this.deltaLat.radians;//this.maxLatitude.radians - this.minLatitude.radians; } /** - * Returns the angular difference between the sector's minimum and maximum longitudes: max - min. + * Returns the angular difference between the sector's minimum and maximum + * longitudes: max - min. * - * @return The angular difference between the sector's minimum and maximum longitudes + * @return The angular difference between the sector's minimum and maximum + * longitudes */ - public final Angle getDeltaLon() - { + public final Angle getDeltaLon() { return this.deltaLon;//Angle.fromDegrees(this.maxLongitude.degrees - this.minLongitude.degrees); } - public final double getDeltaLonDegrees() - { + public final double getDeltaLonDegrees() { return this.deltaLon.degrees;//this.maxLongitude.degrees - this.minLongitude.degrees; } - public final double getDeltaLonRadians() - { + public final double getDeltaLonRadians() { return this.deltaLon.radians;//this.maxLongitude.radians - this.minLongitude.radians; } - public boolean isWithinLatLonLimits() - { + public boolean isWithinLatLonLimits() { return this.minLatitude.degrees >= -90 && this.maxLatitude.degrees <= 90 - && this.minLongitude.degrees >= -180 && this.maxLongitude.degrees <= 180; + && this.minLongitude.degrees >= -180 && this.maxLongitude.degrees <= 180; } - public boolean isSameSector(Iterable corners) - { - if (corners == null) - { + public boolean isSameSector(Iterable corners) { + if (corners == null) { String message = Logging.getMessage("nullValue.LocationsListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (!isSector(corners)) + if (!isSector(corners)) { return false; + } Sector s = Sector.boundingSector(corners); @@ -664,10 +663,8 @@ public boolean isSameSector(Iterable corners) } @SuppressWarnings({"RedundantIfStatement"}) - public static boolean isSector(Iterable corners) - { - if (corners == null) - { + public static boolean isSector(Iterable corners) { + if (corners == null) { String message = Logging.getMessage("nullValue.LocationsListIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -676,37 +673,42 @@ public static boolean isSector(Iterable corners) LatLon[] latlons = new LatLon[5]; int i = 0; - for (LatLon ll : corners) - { - if (i > 4 || ll == null) + for (LatLon ll : corners) { + if (i > 4 || ll == null) { return false; + } latlons[i++] = ll; } - if (!latlons[0].getLatitude().equals(latlons[1].getLatitude())) + if (!latlons[0].getLatitude().equals(latlons[1].getLatitude())) { return false; - if (!latlons[2].getLatitude().equals(latlons[3].getLatitude())) + } + if (!latlons[2].getLatitude().equals(latlons[3].getLatitude())) { return false; - if (!latlons[0].getLongitude().equals(latlons[3].getLongitude())) + } + if (!latlons[0].getLongitude().equals(latlons[3].getLongitude())) { return false; - if (!latlons[1].getLongitude().equals(latlons[2].getLongitude())) + } + if (!latlons[1].getLongitude().equals(latlons[2].getLongitude())) { return false; + } - if (i == 5 && !latlons[4].equals(latlons[0])) + if (i == 5 && !latlons[4].equals(latlons[0])) { return false; + } return true; } /** - * Returns the latitude and longitude of the sector's angular center: (minimum latitude + maximum latitude) / 2, - * (minimum longitude + maximum longitude) / 2. + * Returns the latitude and longitude of the sector's angular center: + * (minimum latitude + maximum latitude) / 2, (minimum longitude + maximum + * longitude) / 2. * * @return The latitude and longitude of the sector's angular center */ - public LatLon getCentroid() - { + public LatLon getCentroid() { Angle la = Angle.fromDegrees(0.5 * (this.getMaxLatitude().degrees + this.getMinLatitude().degrees)); Angle lo = Angle.fromDegrees(0.5 * (this.getMaxLongitude().degrees + this.getMinLongitude().degrees)); return new LatLon(la, lo); @@ -715,17 +717,15 @@ public LatLon getCentroid() /** * Computes the Cartesian coordinates of a Sector's center. * - * @param globe The globe associated with the sector. + * @param globe The globe associated with the sector. * @param exaggeration The vertical exaggeration to apply. * * @return the Cartesian coordinates of the sector's center. * * @throws IllegalArgumentException if globe is null. */ - public Vec4 computeCenterPoint(Globe globe, double exaggeration) - { - if (globe == null) - { + public Vec4 computeCenterPoint(Globe globe, double exaggeration) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -742,17 +742,15 @@ public Vec4 computeCenterPoint(Globe globe, double exaggeration) /** * Computes the Cartesian coordinates of a Sector's corners. * - * @param globe The globe associated with the sector. + * @param globe The globe associated with the sector. * @param exaggeration The vertical exaggeration to apply. * * @return an array of four Cartesian points. * * @throws IllegalArgumentException if globe is null. */ - public Vec4[] computeCornerPoints(Globe globe, double exaggeration) - { - if (globe == null) - { + public Vec4[] computeCornerPoints(Globe globe, double exaggeration) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -773,27 +771,26 @@ public Vec4[] computeCornerPoints(Globe globe, double exaggeration) } /** - * Returns a sphere that minimally surrounds the sector at a specified vertical exaggeration. + * Returns a sphere that minimally surrounds the sector at a specified + * vertical exaggeration. * - * @param globe the globe the sector is associated with - * @param verticalExaggeration the vertical exaggeration to apply to the globe's elevations when computing the - * sphere. - * @param sector the sector to return the bounding sphere for. + * @param globe the globe the sector is associated with + * @param verticalExaggeration the vertical exaggeration to apply to the + * globe's elevations when computing the sphere. + * @param sector the sector to return the bounding sphere for. * * @return The minimal bounding sphere in Cartesian coordinates. * - * @throws IllegalArgumentException if globe or sector is null + * @throws IllegalArgumentException if globe or + * sector is null */ - static public Sphere computeBoundingSphere(Globe globe, double verticalExaggeration, Sector sector) - { - if (globe == null) - { + static public Sphere computeBoundingSphere(Globe globe, double verticalExaggeration, Sector sector) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (sector == null) - { + if (sector == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -819,31 +816,33 @@ static public Sphere computeBoundingSphere(Globe globe, double verticalExaggerat } /** - * Returns a {@link gov.nasa.worldwind.geom.Box} that bounds the specified sector on the surface of the specified - * {@link gov.nasa.worldwind.globes.Globe}. The returned box encloses the globe's surface terrain in the sector, - * according to the specified vertical exaggeration and the globe's minimum and maximum elevations in the sector. If - * the minimum and maximum elevation are equal, this assumes a maximum elevation of 10 + the minimum. If this fails - * to compute a box enclosing the sector, this returns a unit box enclosing one of the boxes corners. - * - * @param globe the globe the extent relates to. + * Returns a {@link gov.nasa.worldwind.geom.Box} that bounds the specified + * sector on the surface of the specified + * {@link gov.nasa.worldwind.globes.Globe}. The returned box encloses the + * globe's surface terrain in the sector, according to the specified + * vertical exaggeration and the globe's minimum and maximum elevations in + * the sector. If the minimum and maximum elevation are equal, this assumes + * a maximum elevation of 10 + the minimum. If this fails to compute a box + * enclosing the sector, this returns a unit box enclosing one of the boxes + * corners. + * + * @param globe the globe the extent relates to. * @param verticalExaggeration the globe's vertical surface exaggeration. - * @param sector a sector on the globe's surface to compute a bounding box for. + * @param sector a sector on the globe's surface to compute a bounding box + * for. * * @return a box enclosing the globe's surface on the specified sector. * * @throws IllegalArgumentException if either the globe or sector is null. */ - public static Box computeBoundingBox(Globe globe, double verticalExaggeration, Sector sector) - { - if (globe == null) - { + public static Box computeBoundingBox(Globe globe, double verticalExaggeration, Sector sector) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (sector == null) - { + if (sector == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -854,34 +853,35 @@ public static Box computeBoundingBox(Globe globe, double verticalExaggeration, S } /** - * Returns a {@link gov.nasa.worldwind.geom.Box} that bounds the specified sector on the surface of the specified - * {@link gov.nasa.worldwind.globes.Globe}. The returned box encloses the globe's surface terrain in the sector, - * according to the specified vertical exaggeration, minimum elevation, and maximum elevation. If the minimum and - * maximum elevation are equal, this assumes a maximum elevation of 10 + the minimum. If this fails to compute a box - * enclosing the sector, this returns a unit box enclosing one of the boxes corners. - * - * @param globe the globe the extent relates to. + * Returns a {@link gov.nasa.worldwind.geom.Box} that bounds the specified + * sector on the surface of the specified + * {@link gov.nasa.worldwind.globes.Globe}. The returned box encloses the + * globe's surface terrain in the sector, according to the specified + * vertical exaggeration, minimum elevation, and maximum elevation. If the + * minimum and maximum elevation are equal, this assumes a maximum elevation + * of 10 + the minimum. If this fails to compute a box enclosing the sector, + * this returns a unit box enclosing one of the boxes corners. + * + * @param globe the globe the extent relates to. * @param verticalExaggeration the globe's vertical surface exaggeration. - * @param sector a sector on the globe's surface to compute a bounding box for. - * @param minElevation the globe's minimum elevation in the sector. - * @param maxElevation the globe's maximum elevation in the sector. + * @param sector a sector on the globe's surface to compute a bounding box + * for. + * @param minElevation the globe's minimum elevation in the sector. + * @param maxElevation the globe's maximum elevation in the sector. * * @return a box enclosing the globe's surface on the specified sector. * * @throws IllegalArgumentException if either the globe or sector is null. */ public static Box computeBoundingBox(Globe globe, double verticalExaggeration, Sector sector, - double minElevation, double maxElevation) - { - if (globe == null) - { + double minElevation, double maxElevation) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (sector == null) - { + if (sector == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -892,8 +892,7 @@ public static Box computeBoundingBox(Globe globe, double verticalExaggeration, S double max = maxElevation * verticalExaggeration; // Ensure the top and bottom heights are not equal. - if (min == max) - { + if (min == max) { max = min + 10; } @@ -907,39 +906,34 @@ public static Box computeBoundingBox(Globe globe, double verticalExaggeration, S Vec4[] points = new Vec4[15]; globe.computePointsFromPositions(sector, 3, 5, elevations, points); - try - { + try { return Box.computeBoundingBox(Arrays.asList(points)); - } - catch (Exception e) - { + } catch (Exception e) { return new Box(points[0]); // unit box around point } } /** - * Returns a cylinder that minimally surrounds the specified sector at a specified vertical exaggeration. + * Returns a cylinder that minimally surrounds the specified sector at a + * specified vertical exaggeration. * - * @param globe The globe associated with the sector. - * @param verticalExaggeration the vertical exaggeration to apply to the minimum and maximum elevations when - * computing the cylinder. - * @param sector the sector to return the bounding cylinder for. + * @param globe The globe associated with the sector. + * @param verticalExaggeration the vertical exaggeration to apply to the + * minimum and maximum elevations when computing the cylinder. + * @param sector the sector to return the bounding cylinder for. * * @return The minimal bounding cylinder in Cartesian coordinates. * * @throws IllegalArgumentException if sector is null */ - static public Cylinder computeBoundingCylinder(Globe globe, double verticalExaggeration, Sector sector) - { - if (globe == null) - { + static public Cylinder computeBoundingCylinder(Globe globe, double verticalExaggeration, Sector sector) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (sector == null) - { + if (sector == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -947,36 +941,34 @@ static public Cylinder computeBoundingCylinder(Globe globe, double verticalExagg double[] minAndMaxElevations = globe.getMinAndMaxElevations(sector); return computeBoundingCylinder(globe, verticalExaggeration, sector, - minAndMaxElevations[0], minAndMaxElevations[1]); + minAndMaxElevations[0], minAndMaxElevations[1]); } /** - * Returns a cylinder that minimally surrounds the specified sector at a specified vertical exaggeration and minimum - * and maximum elevations for the sector. + * Returns a cylinder that minimally surrounds the specified sector at a + * specified vertical exaggeration and minimum and maximum elevations for + * the sector. * - * @param globe The globe associated with the sector. - * @param verticalExaggeration the vertical exaggeration to apply to the minimum and maximum elevations when - * computing the cylinder. - * @param sector the sector to return the bounding cylinder for. - * @param minElevation the minimum elevation of the bounding cylinder. - * @param maxElevation the maximum elevation of the bounding cylinder. + * @param globe The globe associated with the sector. + * @param verticalExaggeration the vertical exaggeration to apply to the + * minimum and maximum elevations when computing the cylinder. + * @param sector the sector to return the bounding cylinder for. + * @param minElevation the minimum elevation of the bounding cylinder. + * @param maxElevation the maximum elevation of the bounding cylinder. * * @return The minimal bounding cylinder in Cartesian coordinates. * * @throws IllegalArgumentException if sector is null */ public static Cylinder computeBoundingCylinder(Globe globe, double verticalExaggeration, Sector sector, - double minElevation, double maxElevation) - { - if (globe == null) - { + double minElevation, double maxElevation) { + if (globe == null) { String msg = Logging.getMessage("nullValue.GlobeIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (sector == null) - { + if (sector == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -986,19 +978,17 @@ public static Cylinder computeBoundingCylinder(Globe globe, double verticalExagg double minHeight = minElevation * verticalExaggeration; double maxHeight = maxElevation * verticalExaggeration; - if (minHeight == maxHeight) + if (minHeight == maxHeight) { maxHeight = minHeight + 1; // ensure the top and bottom of the cylinder won't be coincident - + } List points = new ArrayList(); - for (LatLon ll : sector) - { + for (LatLon ll : sector) { points.add(globe.computePointFromPosition(ll, minHeight)); points.add(globe.computePointFromPosition(ll, maxHeight)); } points.add(globe.computePointFromPosition(sector.getCentroid(), maxHeight)); - if (sector.getDeltaLonDegrees() > 180) - { + if (sector.getDeltaLonDegrees() > 180) { // Need to compute more points to ensure the box encompasses the full sector. Angle cLon = sector.getCentroid().getLongitude(); Angle cLat = sector.getCentroid().getLatitude(); @@ -1016,47 +1006,40 @@ public static Cylinder computeBoundingCylinder(Globe globe, double verticalExagg points.add(globe.computePointFromPosition(cLat, sector.getMaxLongitude(), maxHeight)); } - try - { + try { return Cylinder.computeBoundingCylinder(points); - } - catch (Exception e) - { + } catch (Exception e) { return new Cylinder(points.get(0), points.get(0).add3(Vec4.UNIT_Y), 1); } } - static public Cylinder computeBoundingCylinderOrig(Globe globe, double verticalExaggeration, Sector sector) - { + static public Cylinder computeBoundingCylinderOrig(Globe globe, double verticalExaggeration, Sector sector) { return Cylinder.computeVerticalBoundingCylinder(globe, verticalExaggeration, sector); } /** - * Returns a cylinder that minimally surrounds the specified minimum and maximum elevations in the sector at a - * specified vertical exaggeration. + * Returns a cylinder that minimally surrounds the specified minimum and + * maximum elevations in the sector at a specified vertical exaggeration. * - * @param globe The globe associated with the sector. - * @param verticalExaggeration the vertical exaggeration to apply to the minimum and maximum elevations when - * computing the cylinder. - * @param sector the sector to return the bounding cylinder for. - * @param minElevation the minimum elevation of the bounding cylinder. - * @param maxElevation the maximum elevation of the bounding cylinder. + * @param globe The globe associated with the sector. + * @param verticalExaggeration the vertical exaggeration to apply to the + * minimum and maximum elevations when computing the cylinder. + * @param sector the sector to return the bounding cylinder for. + * @param minElevation the minimum elevation of the bounding cylinder. + * @param maxElevation the maximum elevation of the bounding cylinder. * * @return The minimal bounding cylinder in Cartesian coordinates. * * @throws IllegalArgumentException if sector is null */ public static Cylinder computeBoundingCylinderOrig(Globe globe, double verticalExaggeration, Sector sector, - double minElevation, double maxElevation) - { + double minElevation, double maxElevation) { return Cylinder.computeVerticalBoundingCylinder(globe, verticalExaggeration, sector, minElevation, - maxElevation); + maxElevation); } - public final boolean contains(Angle latitude, Angle longitude) - { - if (latitude == null || longitude == null) - { + public final boolean contains(Angle latitude, Angle longitude) { + if (latitude == null || longitude == null) { String message = Logging.getMessage("nullValue.LatLonIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -1066,20 +1049,21 @@ public final boolean contains(Angle latitude, Angle longitude) } /** - * Determines whether a latitude/longitude position is within the sector. The sector's angles are assumed to be - * normalized to +/- 90 degrees latitude and +/- 180 degrees longitude. The result of the operation is undefined if - * they are not. + * Determines whether a latitude/longitude position is within the sector. + * The sector's angles are assumed to be normalized to +/- 90 degrees + * latitude and +/- 180 degrees longitude. The result of the operation is + * undefined if they are not. * - * @param latLon the position to test, with angles normalized to +/- π latitude and +/- 2π longitude. + * @param latLon the position to test, with angles normalized to +/- π + * latitude and +/- 2π longitude. * - * @return true if the position is within the sector, false otherwise. + * @return true if the position is within the sector, + * false otherwise. * * @throws IllegalArgumentException if latlon is null. */ - public final boolean contains(LatLon latLon) - { - if (latLon == null) - { + public final boolean contains(LatLon latLon) { + if (latLon == null) { String message = Logging.getMessage("nullValue.LatLonIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -1089,137 +1073,157 @@ public final boolean contains(LatLon latLon) } /** - * Determines whether a latitude/longitude postion expressed in radians is within the sector. The sector's angles - * are assumed to be normalized to +/- 90 degrees latitude and +/- 180 degrees longitude. The result of the + * Determines whether a latitude/longitude postion expressed in radians is + * within the sector. The sector's angles are assumed to be normalized to + * +/- 90 degrees latitude and +/- 180 degrees longitude. The result of the * operation is undefined if they are not. * - * @param radiansLatitude the latitude in radians of the position to test, normalized +/- π. - * @param radiansLongitude the longitude in radians of the position to test, normalized +/- 2π. + * @param radiansLatitude the latitude in radians of the position to test, + * normalized +/- π. + * @param radiansLongitude the longitude in radians of the position to test, + * normalized +/- 2π. * - * @return true if the position is within the sector, false otherwise. + * @return true if the position is within the sector, + * false otherwise. */ - public boolean containsRadians(double radiansLatitude, double radiansLongitude) - { + public boolean containsRadians(double radiansLatitude, double radiansLongitude) { return radiansLatitude >= this.minLatitude.radians && radiansLatitude <= this.maxLatitude.radians - && radiansLongitude >= this.minLongitude.radians && radiansLongitude <= this.maxLongitude.radians; + && radiansLongitude >= this.minLongitude.radians && radiansLongitude <= this.maxLongitude.radians; } - public boolean containsDegrees(double degreesLatitude, double degreesLongitude) - { + public boolean containsDegrees(double degreesLatitude, double degreesLongitude) { return degreesLatitude >= this.minLatitude.degrees && degreesLatitude <= this.maxLatitude.degrees - && degreesLongitude >= this.minLongitude.degrees && degreesLongitude <= this.maxLongitude.degrees; + && degreesLongitude >= this.minLongitude.degrees && degreesLongitude <= this.maxLongitude.degrees; } /** - * Determines whether another sector is fully contained within this one. The sector's angles are assumed to be - * normalized to +/- 90 degrees latitude and +/- 180 degrees longitude. The result of the operation is undefined if - * they are not. + * Determines whether another sector is fully contained within this one. The + * sector's angles are assumed to be normalized to +/- 90 degrees latitude + * and +/- 180 degrees longitude. The result of the operation is undefined + * if they are not. * * @param that the sector to test for containment. * - * @return true if this sector fully contains the input sector, otherwise false. + * @return true if this sector fully contains the input sector, + * otherwise false. */ - public boolean contains(Sector that) - { - if (that == null) + public boolean contains(Sector that) { + if (that == null) { return false; + } // Assumes normalized angles -- [-180, 180], [-90, 90] - if (that.minLongitude.degrees < this.minLongitude.degrees) + if (that.minLongitude.degrees < this.minLongitude.degrees) { return false; - if (that.maxLongitude.degrees > this.maxLongitude.degrees) + } + if (that.maxLongitude.degrees > this.maxLongitude.degrees) { return false; - if (that.minLatitude.degrees < this.minLatitude.degrees) + } + if (that.minLatitude.degrees < this.minLatitude.degrees) { return false; + } //noinspection RedundantIfStatement - if (that.maxLatitude.degrees > this.maxLatitude.degrees) + if (that.maxLatitude.degrees > this.maxLatitude.degrees) { return false; + } return true; } /** - * Determines whether this sector intersects another sector's range of latitude and longitude. The sector's angles - * are assumed to be normalized to +/- 90 degrees latitude and +/- 180 degrees longitude. The result of the - * operation is undefined if they are not. + * Determines whether this sector intersects another sector's range of + * latitude and longitude. The sector's angles are assumed to be normalized + * to +/- 90 degrees latitude and +/- 180 degrees longitude. The result of + * the operation is undefined if they are not. * * @param that the sector to test for intersection. * - * @return true if the sectors intersect, otherwise false. + * @return true if the sectors intersect, otherwise + * false. */ - public boolean intersects(Sector that) - { - if (that == null) + public boolean intersects(Sector that) { + if (that == null) { return false; + } // Assumes normalized angles -- [-180, 180], [-90, 90] - if (that.maxLongitude.degrees < this.minLongitude.degrees) + if (that.maxLongitude.degrees < this.minLongitude.degrees) { return false; - if (that.minLongitude.degrees > this.maxLongitude.degrees) + } + if (that.minLongitude.degrees > this.maxLongitude.degrees) { return false; - if (that.maxLatitude.degrees < this.minLatitude.degrees) + } + if (that.maxLatitude.degrees < this.minLatitude.degrees) { return false; + } //noinspection RedundantIfStatement - if (that.minLatitude.degrees > this.maxLatitude.degrees) + if (that.minLatitude.degrees > this.maxLatitude.degrees) { return false; + } return true; } /** - * Determines whether the interiors of this sector and another sector intersect. The sector's angles are assumed to - * be normalized to +/- 90 degrees latitude and +/- 180 degrees longitude. The result of the operation is undefined - * if they are not. + * Determines whether the interiors of this sector and another sector + * intersect. The sector's angles are assumed to be normalized to +/- 90 + * degrees latitude and +/- 180 degrees longitude. The result of the + * operation is undefined if they are not. * * @param that the sector to test for intersection. * - * @return true if the sectors' interiors intersect, otherwise false. + * @return true if the sectors' interiors intersect, otherwise + * false. * * @see #intersects(Sector) */ - public boolean intersectsInterior(Sector that) - { - if (that == null) + public boolean intersectsInterior(Sector that) { + if (that == null) { return false; + } // Assumes normalized angles -- [-180, 180], [-90, 90] - if (that.maxLongitude.degrees <= this.minLongitude.degrees) + if (that.maxLongitude.degrees <= this.minLongitude.degrees) { return false; - if (that.minLongitude.degrees >= this.maxLongitude.degrees) + } + if (that.minLongitude.degrees >= this.maxLongitude.degrees) { return false; - if (that.maxLatitude.degrees <= this.minLatitude.degrees) + } + if (that.maxLatitude.degrees <= this.minLatitude.degrees) { return false; + } //noinspection RedundantIfStatement - if (that.minLatitude.degrees >= this.maxLatitude.degrees) + if (that.minLatitude.degrees >= this.maxLatitude.degrees) { return false; + } return true; } /** - * Determines whether this sector intersects the specified geographic line segment. The line segment is specified by - * a begin location and an end location. The locations are are assumed to be connected by a linear path in - * geographic space. This returns true if any location along that linear path intersects this sector, including the - * begin and end locations. + * Determines whether this sector intersects the specified geographic line + * segment. The line segment is specified by a begin location and an end + * location. The locations are are assumed to be connected by a linear path + * in geographic space. This returns true if any location along that linear + * path intersects this sector, including the begin and end locations. * * @param begin the line segment begin location. - * @param end the line segment end location. + * @param end the line segment end location. * - * @return true true if this sector intersects the line segment, otherwise false. + * @return true true if this sector intersects the line + * segment, otherwise false. * - * @throws IllegalArgumentException if either the begin location or the end location is null. + * @throws IllegalArgumentException if either the begin location or the end + * location is null. */ - public boolean intersectsSegment(LatLon begin, LatLon end) - { - if (begin == null) - { + public boolean intersectsSegment(LatLon begin, LatLon end) { + if (begin == null) { String message = Logging.getMessage("nullValue.BeginIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (end == null) - { + if (end == null) { String message = Logging.getMessage("nullValue.EndIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -1239,112 +1243,119 @@ public boolean intersectsSegment(LatLon begin, LatLon end) Vec4 diff = segmentCenter.subtract3(boxCenter); - if (Math.abs(diff.x) > (boxExtentX + segmentExtent * Math.abs(segmentDirection.x))) - { + if (Math.abs(diff.x) > (boxExtentX + segmentExtent * Math.abs(segmentDirection.x))) { return false; } - if (Math.abs(diff.y) > (boxExtentY + segmentExtent * Math.abs(segmentDirection.y))) - { + if (Math.abs(diff.y) > (boxExtentY + segmentExtent * Math.abs(segmentDirection.y))) { return false; } //noinspection SuspiciousNameCombination Vec4 segmentPerp = new Vec4(segmentDirection.y, -segmentDirection.x, 0); - return Math.abs(segmentPerp.dot3(diff)) <= - (boxExtentX * Math.abs(segmentPerp.x) + boxExtentY * Math.abs(segmentPerp.y)); + return Math.abs(segmentPerp.dot3(diff)) + <= (boxExtentX * Math.abs(segmentPerp.x) + boxExtentY * Math.abs(segmentPerp.y)); } /** - * Determines whether this sector intersects any one of the sectors in the specified iterable. This returns true if - * at least one of the sectors is non-null and intersects this sector. + * Determines whether this sector intersects any one of the sectors in the + * specified iterable. This returns true if at least one of the sectors is + * non-null and intersects this sector. * * @param sectors the sectors to test for intersection. * - * @return true if at least one of the sectors is non-null and intersects this sector, otherwise false. + * @return true if at least one of the sectors is non-null and intersects + * this sector, otherwise false. * * @throws java.lang.IllegalArgumentException if the iterable is null. */ - public boolean intersectsAny(Iterable sectors) - { - if (sectors == null) - { + public boolean intersectsAny(Iterable sectors) { + if (sectors == null) { String msg = Logging.getMessage("nullValue.SectorListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - for (Sector s : sectors) - { - if (s != null && s.intersects(this)) + for (Sector s : sectors) { + if (s != null && s.intersects(this)) { return true; + } } return false; } /** - * Returns a new sector whose angles are the extremes of the this sector and another. The new sector's minimum - * latitude and longitude will be the minimum of the two sectors. The new sector's maximum latitude and longitude - * will be the maximum of the two sectors. The sectors are assumed to be normalized to +/- 90 degrees latitude and - * +/- 180 degrees longitude. The result of the operation is undefined if they are not. + * Returns a new sector whose angles are the extremes of the this sector and + * another. The new sector's minimum latitude and longitude will be the + * minimum of the two sectors. The new sector's maximum latitude and + * longitude will be the maximum of the two sectors. The sectors are assumed + * to be normalized to +/- 90 degrees latitude and +/- 180 degrees + * longitude. The result of the operation is undefined if they are not. * * @param that the sector to join with this. * - * @return A new sector formed from the extremes of the two sectors, or this if the incoming sector is - * null. + * @return A new sector formed from the extremes of the two sectors, or + * this if the incoming sector is null. */ - public final Sector union(Sector that) - { - if (that == null) + public final Sector union(Sector that) { + if (that == null) { return this; + } Angle minLat = this.minLatitude; Angle maxLat = this.maxLatitude; Angle minLon = this.minLongitude; Angle maxLon = this.maxLongitude; - if (that.minLatitude.degrees < this.minLatitude.degrees) + if (that.minLatitude.degrees < this.minLatitude.degrees) { minLat = that.minLatitude; - if (that.maxLatitude.degrees > this.maxLatitude.degrees) + } + if (that.maxLatitude.degrees > this.maxLatitude.degrees) { maxLat = that.maxLatitude; - if (that.minLongitude.degrees < this.minLongitude.degrees) + } + if (that.minLongitude.degrees < this.minLongitude.degrees) { minLon = that.minLongitude; - if (that.maxLongitude.degrees > this.maxLongitude.degrees) + } + if (that.maxLongitude.degrees > this.maxLongitude.degrees) { maxLon = that.maxLongitude; + } return new Sector(minLat, maxLat, minLon, maxLon); } - public final Sector union(Angle latitude, Angle longitude) - { - if (latitude == null || longitude == null) + public final Sector union(Angle latitude, Angle longitude) { + if (latitude == null || longitude == null) { return this; + } Angle minLat = this.minLatitude; Angle maxLat = this.maxLatitude; Angle minLon = this.minLongitude; Angle maxLon = this.maxLongitude; - if (latitude.degrees < this.minLatitude.degrees) + if (latitude.degrees < this.minLatitude.degrees) { minLat = latitude; - if (latitude.degrees > this.maxLatitude.degrees) + } + if (latitude.degrees > this.maxLatitude.degrees) { maxLat = latitude; - if (longitude.degrees < this.minLongitude.degrees) + } + if (longitude.degrees < this.minLongitude.degrees) { minLon = longitude; - if (longitude.degrees > this.maxLongitude.degrees) + } + if (longitude.degrees > this.maxLongitude.degrees) { maxLon = longitude; + } return new Sector(minLat, maxLat, minLon, maxLon); } - public static Sector union(Sector sectorA, Sector sectorB) - { - if (sectorA == null || sectorB == null) - { - if (sectorA == sectorB) + public static Sector union(Sector sectorA, Sector sectorB) { + if (sectorA == null || sectorB == null) { + if (sectorA == sectorB) { return sectorA; + } return sectorB == null ? sectorA : sectorB; } @@ -1352,10 +1363,8 @@ public static Sector union(Sector sectorA, Sector sectorB) return sectorA.union(sectorB); } - public static Sector union(Iterable sectors) - { - if (sectors == null) - { + public static Sector union(Iterable sectors) { + if (sectors == null) { String msg = Logging.getMessage("nullValue.SectorListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -1366,74 +1375,79 @@ public static Sector union(Iterable sectors) Angle minLon = Angle.POS180; Angle maxLon = Angle.NEG180; - for (Sector s : sectors) - { - if (s == null) + for (Sector s : sectors) { + if (s == null) { continue; + } - for (LatLon p : s) - { - if (p.getLatitude().degrees < minLat.degrees) + for (LatLon p : s) { + if (p.getLatitude().degrees < minLat.degrees) { minLat = p.getLatitude(); - if (p.getLatitude().degrees > maxLat.degrees) + } + if (p.getLatitude().degrees > maxLat.degrees) { maxLat = p.getLatitude(); - if (p.getLongitude().degrees < minLon.degrees) + } + if (p.getLongitude().degrees < minLon.degrees) { minLon = p.getLongitude(); - if (p.getLongitude().degrees > maxLon.degrees) + } + if (p.getLongitude().degrees > maxLon.degrees) { maxLon = p.getLongitude(); + } } } return new Sector(minLat, maxLat, minLon, maxLon); } - public final Sector intersection(Sector that) - { - if (that == null) + public final Sector intersection(Sector that) { + if (that == null) { return this; + } Angle minLat, maxLat; minLat = (this.minLatitude.degrees > that.minLatitude.degrees) ? this.minLatitude : that.minLatitude; maxLat = (this.maxLatitude.degrees < that.maxLatitude.degrees) ? this.maxLatitude : that.maxLatitude; - if (minLat.degrees > maxLat.degrees) + if (minLat.degrees > maxLat.degrees) { return null; + } Angle minLon, maxLon; minLon = (this.minLongitude.degrees > that.minLongitude.degrees) ? this.minLongitude : that.minLongitude; maxLon = (this.maxLongitude.degrees < that.maxLongitude.degrees) ? this.maxLongitude : that.maxLongitude; - if (minLon.degrees > maxLon.degrees) + if (minLon.degrees > maxLon.degrees) { return null; + } return new Sector(minLat, maxLat, minLon, maxLon); } - public final Sector intersection(Angle latitude, Angle longitude) - { - if (latitude == null || longitude == null) + public final Sector intersection(Angle latitude, Angle longitude) { + if (latitude == null || longitude == null) { return this; + } - if (!this.contains(latitude, longitude)) + if (!this.contains(latitude, longitude)) { return null; + } return new Sector(latitude, latitude, longitude, longitude); } /** - * Returns the intersection of all sectors in the specified iterable. This returns a non-null sector if the iterable - * contains at least one non-null entry and all non-null entries intersect. The returned sector represents the - * geographic region in which all sectors intersect. This returns null if at least one of the sectors does not - * intersect the others. + * Returns the intersection of all sectors in the specified iterable. This + * returns a non-null sector if the iterable contains at least one non-null + * entry and all non-null entries intersect. The returned sector represents + * the geographic region in which all sectors intersect. This returns null + * if at least one of the sectors does not intersect the others. * * @param sectors the sectors to intersect. * - * @return the intersection of all sectors in the specified iterable, or null if at least one of the sectors does - * not intersect the others. + * @return the intersection of all sectors in the specified iterable, or + * null if at least one of the sectors does not intersect the others. * * @throws java.lang.IllegalArgumentException if the iterable is null. */ - public static Sector intersection(Iterable sectors) - { - if (sectors == null) - { + public static Sector intersection(Iterable sectors) { + if (sectors == null) { String msg = Logging.getMessage("nullValue.SectorListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -1441,22 +1455,21 @@ public static Sector intersection(Iterable sectors) Sector result = null; - for (Sector s : sectors) - { - if (s == null) + for (Sector s : sectors) { + if (s == null) { continue; // ignore null sectors - - if (result == null) + } + if (result == null) { result = s; // start with the first non-null sector - else if ((result = result.intersection(s)) == null) + } else if ((result = result.intersection(s)) == null) { break; // at least one of the sectors does not intersect the others + } } return result; } - public Sector[] subdivide() - { + public Sector[] subdivide() { Angle midLat = Angle.average(this.minLatitude, this.maxLatitude); Angle midLon = Angle.average(this.minLongitude, this.maxLongitude); @@ -1469,22 +1482,19 @@ public Sector[] subdivide() return sectors; } - public Sector[] subdivide(int div) - { + public Sector[] subdivide(int div) { double dLat = this.deltaLat.degrees / div; double dLon = this.deltaLon.degrees / div; Sector[] sectors = new Sector[div * div]; int idx = 0; - for (int row = 0; row < div; row++) - { - for (int col = 0; col < div; col++) - { + for (int row = 0; row < div; row++) { + for (int col = 0; col < div; col++) { sectors[idx++] = Sector.fromDegrees( - this.minLatitude.degrees + dLat * row, - this.minLatitude.degrees + dLat * row + dLat, - this.minLongitude.degrees + dLon * col, - this.minLongitude.degrees + dLon * col + dLon); + this.minLatitude.degrees + dLat * row, + this.minLatitude.degrees + dLat * row + dLat, + this.minLongitude.degrees + dLon * col, + this.minLongitude.degrees + dLon * col + dLon); } } @@ -1492,29 +1502,29 @@ public Sector[] subdivide(int div) } /** - * Returns an approximation of the distance in model coordinates between the surface geometry defined by this sector - * and the specified model coordinate point. The returned value represents the shortest distance between the - * specified point and this sector's corner points or its center point. The draw context defines the globe and the - * elevations that are used to compute the corner points and the center point. - * - * @param dc The draw context defining the surface geometry. + * Returns an approximation of the distance in model coordinates between the + * surface geometry defined by this sector and the specified model + * coordinate point. The returned value represents the shortest distance + * between the specified point and this sector's corner points or its center + * point. The draw context defines the globe and the elevations that are + * used to compute the corner points and the center point. + * + * @param dc The draw context defining the surface geometry. * @param point The model coordinate point to compute a distance to. * - * @return The distance between this sector's surface geometry and the specified point, in model coordinates. + * @return The distance between this sector's surface geometry and the + * specified point, in model coordinates. * * @throws IllegalArgumentException if any argument is null. */ - public double distanceTo(DrawContext dc, Vec4 point) - { - if (dc == null) - { + public double distanceTo(DrawContext dc, Vec4 point) { + if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } - if (point == null) - { + if (point == null) { String message = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -1532,43 +1542,47 @@ public double distanceTo(DrawContext dc, Vec4 point) // Find the minimum distance. double minDistance = d1; - if (minDistance > d2) + if (minDistance > d2) { minDistance = d2; - if (minDistance > d3) + } + if (minDistance > d3) { minDistance = d3; - if (minDistance > d4) + } + if (minDistance > d4) { minDistance = d4; - if (minDistance > d5) + } + if (minDistance > d5) { minDistance = d5; + } return minDistance; } /** - * Returns a four element array containing the Sector's angles in degrees. The returned array is ordered as follows: - * minimum latitude, maximum latitude, minimum longitude, and maximum longitude. + * Returns a four element array containing the Sector's angles in degrees. + * The returned array is ordered as follows: minimum latitude, maximum + * latitude, minimum longitude, and maximum longitude. * * @return four-element array containing the Sector's angles. */ - public double[] toArrayDegrees() - { - return new double[] - { - this.minLatitude.degrees, this.maxLatitude.degrees, - this.minLongitude.degrees, this.maxLongitude.degrees - }; + public double[] toArrayDegrees() { + return new double[]{ + this.minLatitude.degrees, this.maxLatitude.degrees, + this.minLongitude.degrees, this.maxLongitude.degrees + }; } /** - * Returns a {@link java.awt.geom.Rectangle2D} corresponding to this Sector in degrees lat-lon coordinates where x - * corresponds to longitude and y to latitude. + * Returns a {@link java.awt.geom.Rectangle2D} corresponding to this Sector + * in degrees lat-lon coordinates where x corresponds to longitude and y to + * latitude. * - * @return a {@link java.awt.geom.Rectangle2D} corresponding to this Sector in degrees lat-lon coordinates. + * @return a {@link java.awt.geom.Rectangle2D} corresponding to this Sector + * in degrees lat-lon coordinates. */ - public Rectangle2D toRectangleDegrees() - { + public Rectangle2D toRectangleDegrees() { return new Rectangle2D.Double(this.getMinLongitude().degrees, this.getMinLatitude().degrees, - this.getDeltaLonDegrees(), this.getDeltaLatDegrees()); + this.getDeltaLonDegrees(), this.getDeltaLatDegrees()); } /** @@ -1577,8 +1591,7 @@ public Rectangle2D toRectangleDegrees() * @return A string indicating the sector's angles. */ @Override - public String toString() - { + public String toString() { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(this.minLatitude.toString()); @@ -1598,86 +1611,90 @@ public String toString() } /** - * Retrieve the size of this object in bytes. This implementation returns an exact value of the object's size. + * Retrieve the size of this object in bytes. This implementation returns an + * exact value of the object's size. * * @return the size of this object in bytes */ - public long getSizeInBytes() - { + public long getSizeInBytes() { return 4 * minLatitude.getSizeInBytes(); // 4 angles } /** - * Compares this sector to a specified sector according to their minimum latitude, minimum longitude, maximum - * latitude, and maximum longitude, respectively. + * Compares this sector to a specified sector according to their minimum + * latitude, minimum longitude, maximum latitude, and maximum longitude, + * respectively. * * @param that the Sector to compareTo with this. * - * @return -1 if this sector compares less than that specified, 0 if they're equal, and 1 if it compares greater. + * @return -1 if this sector compares less than that specified, 0 if they're + * equal, and 1 if it compares greater. * * @throws IllegalArgumentException if that is null */ - public int compareTo(Sector that) - { - if (that == null) - { + public int compareTo(Sector that) { + if (that == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (this.getMinLatitude().compareTo(that.getMinLatitude()) < 0) + if (this.getMinLatitude().compareTo(that.getMinLatitude()) < 0) { return -1; + } - if (this.getMinLatitude().compareTo(that.getMinLatitude()) > 0) + if (this.getMinLatitude().compareTo(that.getMinLatitude()) > 0) { return 1; + } - if (this.getMinLongitude().compareTo(that.getMinLongitude()) < 0) + if (this.getMinLongitude().compareTo(that.getMinLongitude()) < 0) { return -1; + } - if (this.getMinLongitude().compareTo(that.getMinLongitude()) > 0) + if (this.getMinLongitude().compareTo(that.getMinLongitude()) > 0) { return 1; + } - if (this.getMaxLatitude().compareTo(that.getMaxLatitude()) < 0) + if (this.getMaxLatitude().compareTo(that.getMaxLatitude()) < 0) { return -1; + } - if (this.getMaxLatitude().compareTo(that.getMaxLatitude()) > 0) + if (this.getMaxLatitude().compareTo(that.getMaxLatitude()) > 0) { return 1; + } - if (this.getMaxLongitude().compareTo(that.getMaxLongitude()) < 0) + if (this.getMaxLongitude().compareTo(that.getMaxLongitude()) < 0) { return -1; + } - if (this.getMaxLongitude().compareTo(that.getMaxLongitude()) > 0) + if (this.getMaxLongitude().compareTo(that.getMaxLongitude()) > 0) { return 1; + } return 0; } /** - * Creates an iterator over the four corners of the sector, starting with the southwest position and continuing - * counter-clockwise. + * Creates an iterator over the four corners of the sector, starting with + * the southwest position and continuing counter-clockwise. * * @return an iterator for the sector. */ - public Iterator iterator() - { - return new Iterator() - { + public Iterator iterator() { + return new Iterator() { private int position = 0; - public boolean hasNext() - { + public boolean hasNext() { return this.position < 4; } - public LatLon next() - { - if (this.position > 3) + public LatLon next() { + if (this.position > 3) { throw new NoSuchElementException(); + } LatLon p; - switch (this.position) - { + switch (this.position) { case 0: p = new LatLon(Sector.this.getMinLatitude(), Sector.this.getMinLongitude()); break; @@ -1696,24 +1713,22 @@ public LatLon next() return p; } - public void remove() - { + public void remove() { throw new UnsupportedOperationException(); } }; } /** - * Returns the coordinates of the sector as a list, in the order minLat, maxLat, minLon, maxLon. + * Returns the coordinates of the sector as a list, in the order minLat, + * maxLat, minLon, maxLon. * * @return the list of sector coordinates. */ - public List asList() - { + public List asList() { ArrayList list = new ArrayList(4); - for (LatLon ll : this) - { + for (LatLon ll : this) { list.add(ll); } @@ -1721,42 +1736,38 @@ public List asList() } /** - * Returns the coordinates of the sector as an array of values in degrees, in the order minLat, maxLat, minLon, - * maxLon. + * Returns the coordinates of the sector as an array of values in degrees, + * in the order minLat, maxLat, minLon, maxLon. * * @return the array of sector coordinates. */ - public double[] asDegreesArray() - { - return new double[] - { - this.getMinLatitude().degrees, this.getMaxLatitude().degrees, - this.getMinLongitude().degrees, this.getMaxLongitude().degrees - }; + public double[] asDegreesArray() { + return new double[]{ + this.getMinLatitude().degrees, this.getMaxLatitude().degrees, + this.getMinLongitude().degrees, this.getMaxLongitude().degrees + }; } /** - * Returns the coordinates of the sector as an array of values in radians, in the order minLat, maxLat, minLon, - * maxLon. + * Returns the coordinates of the sector as an array of values in radians, + * in the order minLat, maxLat, minLon, maxLon. * * @return the array of sector coordinates. */ - public double[] asRadiansArray() - { - return new double[] - { - this.getMinLatitude().radians, this.getMaxLatitude().radians, - this.getMinLongitude().radians, this.getMaxLongitude().radians - }; + public double[] asRadiansArray() { + return new double[]{ + this.getMinLatitude().radians, this.getMaxLatitude().radians, + this.getMinLongitude().radians, this.getMaxLongitude().radians + }; } /** * Returns a list of the Lat/Lon coordinates of a Sector's corners. * - * @return an array of the four corner locations, in the order SW, SE, NE, NW + * @return an array of the four corner locations, in the order SW, SE, NE, + * NW */ - public LatLon[] getCorners() - { + public LatLon[] getCorners() { LatLon[] corners = new LatLon[4]; corners[0] = new LatLon(this.minLatitude, this.minLongitude); @@ -1768,32 +1779,38 @@ public LatLon[] getCorners() } /** - * Tests the equality of the sectors' angles. Sectors are equal if all of their corresponding angles are equal. + * Tests the equality of the sectors' angles. Sectors are equal if all of + * their corresponding angles are equal. * * @param o the sector to compareTo with this. * - * @return true if the four corresponding angles of each sector are equal, false - * otherwise. + * @return true if the four corresponding angles of each sector + * are equal, false otherwise. */ @Override - public boolean equals(Object o) - { - if (this == o) + public boolean equals(Object o) { + if (this == o) { return true; - if (o == null || getClass() != o.getClass()) + } + if (o == null || getClass() != o.getClass()) { return false; + } final gov.nasa.worldwind.geom.Sector sector = (gov.nasa.worldwind.geom.Sector) o; - if (!maxLatitude.equals(sector.maxLatitude)) + if (!maxLatitude.equals(sector.maxLatitude)) { return false; - if (!maxLongitude.equals(sector.maxLongitude)) + } + if (!maxLongitude.equals(sector.maxLongitude)) { return false; - if (!minLatitude.equals(sector.minLatitude)) + } + if (!minLatitude.equals(sector.minLatitude)) { return false; + } //noinspection RedundantIfStatement - if (!minLongitude.equals(sector.minLongitude)) + if (!minLongitude.equals(sector.minLongitude)) { return false; + } return true; } @@ -1804,8 +1821,7 @@ public boolean equals(Object o) * @return a hash code incorporating the sector's four angles. */ @Override - public int hashCode() - { + public int hashCode() { int result; result = minLatitude.hashCode(); result = 29 * result + maxLatitude.hashCode(); @@ -1813,4 +1829,4 @@ public int hashCode() result = 29 * result + maxLongitude.hashCode(); return result; } -} \ No newline at end of file +} diff --git a/src/gov/nasa/worldwind/geom/Triangle.java b/src/gov/nasa/worldwind/geom/Triangle.java index e43cc850f1..16da4df598 100644 --- a/src/gov/nasa/worldwind/geom/Triangle.java +++ b/src/gov/nasa/worldwind/geom/Triangle.java @@ -39,8 +39,8 @@ * @author Eric Dalgliesh 30/11/2006 * @version $Id: Triangle.java 1171 2013-02-11 21:45:02Z dcollins $ */ -public class Triangle -{ +public class Triangle { + private static final double EPSILON = 0.0000001; // used in intersects method private final Vec4 a; @@ -48,8 +48,8 @@ public class Triangle private final Vec4 c; /** - * Construct a triangle from three counter-clockwise ordered vertices. The front face of the triangle is determined - * by the right-hand rule. + * Construct a triangle from three counter-clockwise ordered vertices. The + * front face of the triangle is determined by the right-hand rule. * * @param a the first vertex. * @param b the second vertex. @@ -57,10 +57,8 @@ public class Triangle * * @throws IllegalArgumentException if any vertex is null. */ - public Triangle(Vec4 a, Vec4 b, Vec4 c) - { - if (a == null || b == null || c == null) - { + public Triangle(Vec4 a, Vec4 b, Vec4 c) { + if (a == null || b == null || c == null) { String msg = Logging.getMessage("nullValue.PointIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -76,8 +74,7 @@ public Triangle(Vec4 a, Vec4 b, Vec4 c) * * @return the first vertex. */ - public Vec4 getA() - { + public Vec4 getA() { return this.a; } @@ -86,8 +83,7 @@ public Vec4 getA() * * @return the second vertex. */ - public Vec4 getB() - { + public Vec4 getB() { return this.b; } @@ -96,8 +92,7 @@ public Vec4 getB() * * @return the third vertex. */ - public Vec4 getC() - { + public Vec4 getC() { return this.c; } @@ -111,7 +106,6 @@ public Vec4 getC() // // return new gov.nasa.worldwind.geom.Plane(n); // } - // private Point temporaryIntersectPlaneAndLine(Line line, Plane plane) // { // Vector n = line.getDirection(); @@ -130,7 +124,6 @@ public Vec4 getC() // d = 1/d; // return new Triangle(this.a.multiply(d), this.b.multiply(d), this.c.multiply(d)); // } - /** * Indicates whether a specified point is on the triangle. * @@ -138,10 +131,10 @@ public Vec4 getC() * * @return true if the point is on the triangle, otherwise false. */ - public boolean contains(Vec4 p) - { - if (p == null) + public boolean contains(Vec4 p) { + if (p == null) { return false; + } // Compute vectors Vec4 v0 = this.c.subtract3(this.a); @@ -174,56 +167,59 @@ public boolean contains(Vec4 p) * * @param line the line to test. * - * @return the point of intersection if the line intersects the triangle, otherwise null. + * @return the point of intersection if the line intersects the triangle, + * otherwise null. * * @throws IllegalArgumentException if the line is null. */ - public Vec4 intersect(Line line) - { + public Vec4 intersect(Line line) { Intersection intersection = intersect(line, this.a, this.b, this.c); return intersection != null ? intersection.getIntersectionPoint() : null; } /** - * Determines the intersection of a specified line with a specified triangle. The triangle is specified by three - * points ordered counterclockwise. The triangle's front face is determined by the right-hand rule. + * Determines the intersection of a specified line with a specified + * triangle. The triangle is specified by three points ordered + * counterclockwise. The triangle's front face is determined by the + * right-hand rule. * * @param line the line to test. - * @param a the first vertex of the triangle. - * @param b the second vertex of the triangle. - * @param c the third vertex of the triangle. + * @param a the first vertex of the triangle. + * @param b the second vertex of the triangle. + * @param c the third vertex of the triangle. * - * @return the point of intersection if the line intersects the triangle, otherwise null. + * @return the point of intersection if the line intersects the triangle, + * otherwise null. * - * @throws IllegalArgumentException if the line or any of the triangle vertices is null. + * @throws IllegalArgumentException if the line or any of the triangle + * vertices is null. */ - public static Intersection intersect(Line line, Vec4 a, Vec4 b, Vec4 c) - { + public static Intersection intersect(Line line, Vec4 a, Vec4 b, Vec4 c) { return intersect(line, a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z); } /** - * Determines the intersection of a specified line with a triangle specified by individual coordinates. + * Determines the intersection of a specified line with a triangle specified + * by individual coordinates. * * @param line the line to test. - * @param vax the X coordinate of the first vertex of the triangle. - * @param vay the Y coordinate of the first vertex of the triangle. - * @param vaz the Z coordinate of the first vertex of the triangle. - * @param vbx the X coordinate of the second vertex of the triangle. - * @param vby the Y coordinate of the second vertex of the triangle. - * @param vbz the Z coordinate of the second vertex of the triangle. - * @param vcx the X coordinate of the third vertex of the triangle. - * @param vcy the Y coordinate of the third vertex of the triangle. - * @param vcz the Z coordinate of the third vertex of the triangle. + * @param vax the X coordinate of the first vertex of the triangle. + * @param vay the Y coordinate of the first vertex of the triangle. + * @param vaz the Z coordinate of the first vertex of the triangle. + * @param vbx the X coordinate of the second vertex of the triangle. + * @param vby the Y coordinate of the second vertex of the triangle. + * @param vbz the Z coordinate of the second vertex of the triangle. + * @param vcx the X coordinate of the third vertex of the triangle. + * @param vcy the Y coordinate of the third vertex of the triangle. + * @param vcz the Z coordinate of the third vertex of the triangle. * - * @return the point of intersection if the line intersects the triangle, otherwise null. + * @return the point of intersection if the line intersects the triangle, + * otherwise null. */ public static Intersection intersect(Line line, - double vax, double vay, double vaz, double vbx, double vby, double vbz, double vcx, double vcy, double vcz) - { - if (line == null) - { + double vax, double vay, double vaz, double vbx, double vby, double vbz, double vcx, double vcy, double vcz) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -232,7 +228,6 @@ public static Intersection intersect(Line line, // taken from Moller and Trumbore // http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/ // Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf - Vec4 origin = line.getOrigin(); Vec4 dir = line.getDirection(); @@ -254,7 +249,9 @@ public static Intersection intersect(Line line, double det = edge1x * pvecx + edge1y * pvecy + edge1z * pvecz; // edge1 dot pvec if (det > -EPSILON && det < EPSILON) // If det is near zero, then ray lies on plane of triangle + { return null; + } double detInv = 1d / det; @@ -265,8 +262,9 @@ public static Intersection intersect(Line line, // Calculate u parameter and test bounds: 1/det * tvec dot pvec double u = detInv * (tvecx * pvecx + tvecy * pvecy + tvecz * pvecz); - if (u < 0 || u > 1) + if (u < 0 || u > 1) { return null; + } // Prepare to test v parameter: tvec cross edge1 double qvecx = (tvecy * edge1z) - (tvecz * edge1y); @@ -275,13 +273,15 @@ public static Intersection intersect(Line line, // Calculate v parameter and test bounds: 1/det * dir dot qvec double v = detInv * (dir.x * qvecx + dir.y * qvecy + dir.z * qvecz); - if (v < 0 || u + v > 1) + if (v < 0 || u + v > 1) { return null; + } // Calculate the point of intersection on the line: t = 1/det * edge2 dot qvec; double t = detInv * (edge2x * qvecx + edge2y * qvecy + edge2z * qvecz); - if (t < 0) + if (t < 0) { return null; + } return new Intersection(line.getPointAt(t), t, false); } @@ -289,25 +289,24 @@ public static Intersection intersect(Line line, /** * Compute the intersections of a line with a triangle strip. * - * @param line the line to intersect. + * @param line the line to intersect. * @param vertices the tri-strip vertices. - * @param indices the indices forming the tri-strip. + * @param indices the indices forming the tri-strip. * - * @return the list of intersections with the line and the tri-strip, or null if there are no intersections. + * @return the list of intersections with the line and the tri-strip, or + * null if there are no intersections. * - * @throws IllegalArgumentException if the line, vertex buffer or index buffer is null. + * @throws IllegalArgumentException if the line, vertex buffer or index + * buffer is null. */ - public static List intersectTriStrip(final Line line, FloatBuffer vertices, IntBuffer indices) - { - if (line == null) - { + public static List intersectTriStrip(final Line line, FloatBuffer vertices, IntBuffer indices) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (vertices == null || indices == null) - { + if (vertices == null || indices == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -315,8 +314,7 @@ public static List intersectTriStrip(final Line line, FloatBuffer List intersections = null; - for (int n = indices.position(); n < indices.limit() - 2; n++) - { + for (int n = indices.position(); n < indices.limit() - 2; n++) { Intersection intersection; int i = indices.get(n) * 3; @@ -326,14 +324,14 @@ public static List intersectTriStrip(final Line line, FloatBuffer // The triangle intersect method detects front and back face intersections so there's no reason to // order the vertices. intersection = intersect(line, - vertices.get(i), vertices.get(i + 1), vertices.get(i + 2), - vertices.get(j), vertices.get(j + 1), vertices.get(j + 2), - vertices.get(k), vertices.get(k + 1), vertices.get(k + 2)); + vertices.get(i), vertices.get(i + 1), vertices.get(i + 2), + vertices.get(j), vertices.get(j + 1), vertices.get(j + 2), + vertices.get(k), vertices.get(k + 1), vertices.get(k + 2)); - if (intersection != null) - { - if (intersections == null) + if (intersection != null) { + if (intersections == null) { intersections = new ArrayList(); + } intersections.add(intersection); } } @@ -344,32 +342,30 @@ public static List intersectTriStrip(final Line line, FloatBuffer /** * Compute the intersections of a line with a triangle strip. * - * @param line the line to intersect. + * @param line the line to intersect. * @param vertices the tri-strip vertices. - * @param indices the indices forming the tri-strip. + * @param indices the indices forming the tri-strip. * - * @return the list of intersections with the line and the triangle strip, or null if there are no intersections. + * @return the list of intersections with the line and the triangle strip, + * or null if there are no intersections. * - * @throws IllegalArgumentException if the line, vertex array or index buffer is null. + * @throws IllegalArgumentException if the line, vertex array or index + * buffer is null. */ - public static List intersectTriStrip(final Line line, Vec4[] vertices, IntBuffer indices) - { - if (line == null) - { + public static List intersectTriStrip(final Line line, Vec4[] vertices, IntBuffer indices) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (vertices == null) - { + if (vertices == null) { String msg = Logging.getMessage("nullValue.ArrayIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (indices == null) - { + if (indices == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -377,8 +373,7 @@ public static List intersectTriStrip(final Line line, Vec4[] verti List intersections = null; - for (int n = indices.position(); n < indices.limit() - 1; n++) - { + for (int n = indices.position(); n < indices.limit() - 1; n++) { Intersection intersection; int i = indices.get(n) * 3; @@ -389,10 +384,10 @@ public static List intersectTriStrip(final Line line, Vec4[] verti // order the vertices. intersection = intersect(line, vertices[i], vertices[j], vertices[k]); - if (intersection != null) - { - if (intersections == null) + if (intersection != null) { + if (intersections == null) { intersections = new ArrayList(); + } intersections.add(intersection); } } @@ -403,25 +398,24 @@ public static List intersectTriStrip(final Line line, Vec4[] verti /** * Compute the intersections of a line with a triangle fan. * - * @param line the line to intersect. + * @param line the line to intersect. * @param vertices the tri-fan vertices. - * @param indices the indices forming the tri-fan. + * @param indices the indices forming the tri-fan. * - * @return the list of intersections with the line and the triangle fan, or null if there are no intersections. + * @return the list of intersections with the line and the triangle fan, or + * null if there are no intersections. * - * @throws IllegalArgumentException if the line, vertex buffer or index buffer is null. + * @throws IllegalArgumentException if the line, vertex buffer or index + * buffer is null. */ - public static List intersectTriFan(final Line line, FloatBuffer vertices, IntBuffer indices) - { - if (line == null) - { + public static List intersectTriFan(final Line line, FloatBuffer vertices, IntBuffer indices) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (vertices == null || indices == null) - { + if (vertices == null || indices == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -437,8 +431,7 @@ public static List intersectTriFan(final Line line, FloatBuffer ve float v0z = vertices.get(k * 3 + 2); // Starting with the second position in the index buffer, get subsequent indices and vertices. - for (int n = indices.position(); n < indices.limit() - 1; n++) - { + for (int n = indices.position(); n < indices.limit() - 1; n++) { Intersection intersection; int i = indices.get(n) * 3; @@ -447,14 +440,14 @@ public static List intersectTriFan(final Line line, FloatBuffer ve // The triangle intersect method detects front and back face intersections so there's no reason to // order the vertices. intersection = intersect(line, - v0x, v0y, v0z, - vertices.get(i), vertices.get(i + 1), vertices.get(i + 2), - vertices.get(j), vertices.get(j + 1), vertices.get(j + 2)); + v0x, v0y, v0z, + vertices.get(i), vertices.get(i + 1), vertices.get(i + 2), + vertices.get(j), vertices.get(j + 1), vertices.get(j + 2)); - if (intersection != null) - { - if (intersections == null) + if (intersection != null) { + if (intersections == null) { intersections = new ArrayList(); + } intersections.add(intersection); } } @@ -465,32 +458,30 @@ public static List intersectTriFan(final Line line, FloatBuffer ve /** * Compute the intersections of a line with a triangle fan. * - * @param line the line to intersect. + * @param line the line to intersect. * @param vertices the tri-fan vertices. - * @param indices the indices forming the tri-fan. + * @param indices the indices forming the tri-fan. * - * @return the list of intersections with the line and the triangle fan, or null if there are no intersections. + * @return the list of intersections with the line and the triangle fan, or + * null if there are no intersections. * - * @throws IllegalArgumentException if the line, vertex array or index buffer is null. + * @throws IllegalArgumentException if the line, vertex array or index + * buffer is null. */ - public static List intersectTriFan(final Line line, Vec4[] vertices, IntBuffer indices) - { - if (line == null) - { + public static List intersectTriFan(final Line line, Vec4[] vertices, IntBuffer indices) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (vertices == null) - { + if (vertices == null) { String msg = Logging.getMessage("nullValue.ArrayIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (indices == null) - { + if (indices == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -500,8 +491,7 @@ public static List intersectTriFan(final Line line, Vec4[] vertice Vec4 v0 = vertices[0]; - for (int n = indices.position() + 1; n < indices.limit() - 1; n++) - { + for (int n = indices.position() + 1; n < indices.limit() - 1; n++) { Intersection intersection; Vec4 v1 = vertices[indices.get(n)]; @@ -510,10 +500,10 @@ public static List intersectTriFan(final Line line, Vec4[] vertice // The triangle intersect method detects front and back face intersections so there's no reason to // order the vertices. intersection = intersect(line, v0, v1, v2); - if (intersection != null) - { - if (intersections == null) + if (intersection != null) { + if (intersections == null) { intersections = new ArrayList(); + } intersections.add(intersection); } } @@ -524,24 +514,23 @@ public static List intersectTriFan(final Line line, Vec4[] vertice /** * Compute the intersections of a line with a collection of triangles. * - * @param line the line to intersect. - * @param vertices the triangles, arranged in a buffer as GL_TRIANGLES (9 floats per triangle). + * @param line the line to intersect. + * @param vertices the triangles, arranged in a buffer as GL_TRIANGLES (9 + * floats per triangle). * - * @return the list of intersections with the line and the triangles, or null if there are no intersections. + * @return the list of intersections with the line and the triangles, or + * null if there are no intersections. * * @throws IllegalArgumentException if the line or vertex buffer is null. */ - public static List intersectTriangles(final Line line, FloatBuffer vertices) - { - if (line == null) - { + public static List intersectTriangles(final Line line, FloatBuffer vertices) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (vertices == null) - { + if (vertices == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -551,17 +540,16 @@ public static List intersectTriangles(final Line line, FloatBuffer vertices.rewind(); - while (vertices.limit() - vertices.position() >= 9) - { + while (vertices.limit() - vertices.position() >= 9) { Intersection intersection = intersect(line, - vertices.get(), vertices.get(), vertices.get(), - vertices.get(), vertices.get(), vertices.get(), - vertices.get(), vertices.get(), vertices.get()); + vertices.get(), vertices.get(), vertices.get(), + vertices.get(), vertices.get(), vertices.get(), + vertices.get(), vertices.get(), vertices.get()); - if (intersection != null) - { - if (intersections == null) + if (intersection != null) { + if (intersections == null) { intersections = new ArrayList(); + } intersections.add(intersection); } } @@ -572,25 +560,25 @@ public static List intersectTriangles(final Line line, FloatBuffer /** * Compute the intersections of a line with a collection of triangles. * - * @param line the line to intersect. - * @param vertices the triangles, arranged in a buffer as GL_TRIANGLES (9 floats per triangle). - * @param indices the indices forming the triangles. + * @param line the line to intersect. + * @param vertices the triangles, arranged in a buffer as GL_TRIANGLES (9 + * floats per triangle). + * @param indices the indices forming the triangles. * - * @return the list of intersections with the line and the triangle fan, or null if there are no intersections. + * @return the list of intersections with the line and the triangle fan, or + * null if there are no intersections. * - * @throws IllegalArgumentException if the line, vertex buffer or index buffer is null. + * @throws IllegalArgumentException if the line, vertex buffer or index + * buffer is null. */ - public static List intersectTriangles(final Line line, FloatBuffer vertices, IntBuffer indices) - { - if (line == null) - { + public static List intersectTriangles(final Line line, FloatBuffer vertices, IntBuffer indices) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (vertices == null || indices == null) - { + if (vertices == null || indices == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -598,8 +586,7 @@ public static List intersectTriangles(final Line line, FloatBuffer List intersections = null; - for (int n = indices.position(); n < indices.limit(); n += 3) - { + for (int n = indices.position(); n < indices.limit(); n += 3) { Intersection intersection; int i = indices.get(n) * 3; @@ -607,14 +594,14 @@ public static List intersectTriangles(final Line line, FloatBuffer int k = indices.get(n + 2) * 3; intersection = intersect(line, - vertices.get(i), vertices.get(i + 1), vertices.get(i + 2), - vertices.get(j), vertices.get(j + 1), vertices.get(j + 2), - vertices.get(k), vertices.get(k + 1), vertices.get(k + 2)); + vertices.get(i), vertices.get(i + 1), vertices.get(i + 2), + vertices.get(j), vertices.get(j + 1), vertices.get(j + 2), + vertices.get(k), vertices.get(k + 1), vertices.get(k + 2)); - if (intersection != null) - { - if (intersections == null) + if (intersection != null) { + if (intersections == null) { intersections = new ArrayList(); + } intersections.add(intersection); } } @@ -625,63 +612,63 @@ public static List intersectTriangles(final Line line, FloatBuffer /** * Compute the intersections of a line with a triangle collection. * - * @param line the line to intersect. - * @param vertices the tri-fan vertices, in the order x, y, z, x, y, z, ... - * @param indices the indices forming the tri-fan. - * @param triangleType the type of triangle collection, either GL.GL_TRIANGLE_STRIP or GL.GL_TRIANGLE_FAN. + * @param line the line to intersect. + * @param vertices the tri-fan vertices, in the order x, y, z, x, y, z, ... + * @param indices the indices forming the tri-fan. + * @param triangleType the type of triangle collection, either + * GL.GL_TRIANGLE_STRIP or GL.GL_TRIANGLE_FAN. * - * @return the list of intersections with the line and the triangle fan, or null if there are no intersections. + * @return the list of intersections with the line and the triangle fan, or + * null if there are no intersections. */ public static List intersectTriangleTypes(final Line line, FloatBuffer vertices, IntBuffer indices, - int triangleType) - { - if (triangleType == GL.GL_TRIANGLES) + int triangleType) { + if (triangleType == GL.GL_TRIANGLES) { return Triangle.intersectTriangles(line, vertices, indices); - else if (triangleType == GL.GL_TRIANGLE_STRIP) + } else if (triangleType == GL.GL_TRIANGLE_STRIP) { return Triangle.intersectTriStrip(line, vertices, indices); - else if (triangleType == GL.GL_TRIANGLE_FAN) + } else if (triangleType == GL.GL_TRIANGLE_FAN) { return Triangle.intersectTriFan(line, vertices, indices); + } return null; } /** - * Expands a buffer of indexed triangle vertices to a buffer of non-indexed triangle vertices. + * Expands a buffer of indexed triangle vertices to a buffer of non-indexed + * triangle vertices. * * @param indices the triangle indices. - * @param inBuf the vertex buffer the indices refer to, in the order x, y, z, x, y, z, ... - * @param outBuf the buffer in which to place the expanded triangle vertices. The buffer must have a limit - * sufficient to hold the output vertices. + * @param inBuf the vertex buffer the indices refer to, in the order x, y, + * z, x, y, z, ... + * @param outBuf the buffer in which to place the expanded triangle + * vertices. The buffer must have a limit sufficient to hold the output + * vertices. * - * @throws IllegalArgumentException if the index list or the input or output buffer is null, or if the output buffer - * size is insufficient. + * @throws IllegalArgumentException if the index list or the input or output + * buffer is null, or if the output buffer size is insufficient. */ - public static void expandTriangles(List indices, FloatBuffer inBuf, FloatBuffer outBuf) - { - if (indices == null) - { + public static void expandTriangles(List indices, FloatBuffer inBuf, FloatBuffer outBuf) { + if (indices == null) { String msg = Logging.getMessage("nullValue.ListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (inBuf == null || outBuf == null) - { + if (inBuf == null || outBuf == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } int nunTriangles = indices.size() / 3; - if (nunTriangles * 3 * 3 > outBuf.limit() - outBuf.position()) - { + if (nunTriangles * 3 * 3 > outBuf.limit() - outBuf.position()) { String msg = Logging.getMessage("generic.BufferSize", outBuf.limit() - outBuf.position()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - for (int i = 0; i < indices.size(); i += 3) - { + for (int i = 0; i < indices.size(); i += 3) { int k = indices.get(i) * 3; outBuf.put(inBuf.get(k)).put(inBuf.get(k + 1)).put(inBuf.get(k + 2)); @@ -694,35 +681,34 @@ public static void expandTriangles(List indices, FloatBuffer inBuf, Flo } /** - * Expands a buffer of indexed triangle fan vertices to a buffer of non-indexed general-triangle vertices. + * Expands a buffer of indexed triangle fan vertices to a buffer of + * non-indexed general-triangle vertices. * * @param indices the triangle indices. - * @param inBuf the vertex buffer the indices refer to, in the order x, y, z, x, y, z, ... - * @param outBuf the buffer in which to place the expanded triangle vertices. The buffer must have a limit - * sufficient to hold the output vertices. + * @param inBuf the vertex buffer the indices refer to, in the order x, y, + * z, x, y, z, ... + * @param outBuf the buffer in which to place the expanded triangle + * vertices. The buffer must have a limit sufficient to hold the output + * vertices. * - * @throws IllegalArgumentException if the index list or the input or output buffer is null, or if the output buffer - * size is insufficient. + * @throws IllegalArgumentException if the index list or the input or output + * buffer is null, or if the output buffer size is insufficient. */ - public static void expandTriangleFan(List indices, FloatBuffer inBuf, FloatBuffer outBuf) - { - if (indices == null) - { + public static void expandTriangleFan(List indices, FloatBuffer inBuf, FloatBuffer outBuf) { + if (indices == null) { String msg = Logging.getMessage("nullValue.ListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (inBuf == null || outBuf == null) - { + if (inBuf == null || outBuf == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } int nunTriangles = indices.size() - 2; - if (nunTriangles * 3 * 3 > outBuf.limit() - outBuf.position()) - { + if (nunTriangles * 3 * 3 > outBuf.limit() - outBuf.position()) { String msg = Logging.getMessage("generic.BufferSize", outBuf.limit() - outBuf.position()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -733,8 +719,7 @@ public static void expandTriangleFan(List indices, FloatBuffer inBuf, F float v0y = inBuf.get(k + 1); float v0z = inBuf.get(k + 2); - for (int i = 1; i < indices.size() - 1; i++) - { + for (int i = 1; i < indices.size() - 1; i++) { outBuf.put(v0x).put(v0y).put(v0z); k = indices.get(i) * 3; @@ -746,42 +731,40 @@ public static void expandTriangleFan(List indices, FloatBuffer inBuf, F } /** - * Expands a buffer of indexed triangle strip vertices to a buffer of non-indexed general-triangle vertices. + * Expands a buffer of indexed triangle strip vertices to a buffer of + * non-indexed general-triangle vertices. * * @param indices the triangle indices. - * @param inBuf the vertex buffer the indices refer to, in the order x, y, z, x, y, z, ... - * @param outBuf the buffer in which to place the expanded triangle vertices. The buffer must have a limit - * sufficient to hold the output vertices. + * @param inBuf the vertex buffer the indices refer to, in the order x, y, + * z, x, y, z, ... + * @param outBuf the buffer in which to place the expanded triangle + * vertices. The buffer must have a limit sufficient to hold the output + * vertices. * - * @throws IllegalArgumentException if the index list or the input or output buffer is null, or if the output buffer - * size is insufficient. + * @throws IllegalArgumentException if the index list or the input or output + * buffer is null, or if the output buffer size is insufficient. */ - public static void expandTriangleStrip(List indices, FloatBuffer inBuf, FloatBuffer outBuf) - { - if (indices == null) - { + public static void expandTriangleStrip(List indices, FloatBuffer inBuf, FloatBuffer outBuf) { + if (indices == null) { String msg = Logging.getMessage("nullValue.ListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (inBuf == null || outBuf == null) - { + if (inBuf == null || outBuf == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } int nunTriangles = indices.size() - 2; - if (nunTriangles * 3 * 3 > outBuf.limit() - outBuf.position()) - { + if (nunTriangles * 3 * 3 > outBuf.limit() - outBuf.position()) { String msg = Logging.getMessage("generic.BufferSize", outBuf.limit() - outBuf.position()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - for (int i = 2; i < indices.size(); i++) - { + for (int i = 2; i < indices.size(); i++) { int k = indices.get(i - 2) * 3; outBuf.put(inBuf.get(k)).put(inBuf.get(k + 1)).put(inBuf.get(k + 2)); @@ -793,55 +776,46 @@ public static void expandTriangleStrip(List indices, FloatBuffer inBuf, } } - public static void expandTriangles(List indices, IntBuffer outBuf) - { - if (indices == null) - { + public static void expandTriangles(List indices, IntBuffer outBuf) { + if (indices == null) { String msg = Logging.getMessage("nullValue.ListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (outBuf == null) - { + if (outBuf == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } int numTriangles = indices.size() / 3; - if (numTriangles * 3 > outBuf.limit() - outBuf.position()) - { + if (numTriangles * 3 > outBuf.limit() - outBuf.position()) { String msg = Logging.getMessage("generic.BufferSize", outBuf.limit() - outBuf.position()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - for (int i = 0; i < indices.size(); i++) - { + for (int i = 0; i < indices.size(); i++) { outBuf.put(indices.get(i)); } } - public static void expandTriangleFan(List indices, IntBuffer outBuf) - { - if (indices == null) - { + public static void expandTriangleFan(List indices, IntBuffer outBuf) { + if (indices == null) { String msg = Logging.getMessage("nullValue.ListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (outBuf == null) - { + if (outBuf == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } int nunTriangles = indices.size() - 2; - if (nunTriangles * 3 > outBuf.limit() - outBuf.position()) - { + if (nunTriangles * 3 > outBuf.limit() - outBuf.position()) { String msg = Logging.getMessage("generic.BufferSize", outBuf.limit() - outBuf.position()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -849,40 +823,34 @@ public static void expandTriangleFan(List indices, IntBuffer outBuf) int k0 = indices.get(0); - for (int i = 1; i < indices.size() - 1; i++) - { + for (int i = 1; i < indices.size() - 1; i++) { outBuf.put(k0); outBuf.put(indices.get(i)); outBuf.put(indices.get(i + 1)); } } - public static void expandTriangleStrip(List indices, IntBuffer outBuf) - { - if (indices == null) - { + public static void expandTriangleStrip(List indices, IntBuffer outBuf) { + if (indices == null) { String msg = Logging.getMessage("nullValue.ListIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - if (outBuf == null) - { + if (outBuf == null) { String msg = Logging.getMessage("nullValue.BufferIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } int nunTriangles = indices.size() - 2; - if (nunTriangles * 3 > outBuf.limit() - outBuf.position()) - { + if (nunTriangles * 3 > outBuf.limit() - outBuf.position()) { String msg = Logging.getMessage("generic.BufferSize", outBuf.limit() - outBuf.position()); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - for (int i = 2; i < indices.size(); i++) - { + for (int i = 2; i < indices.size(); i++) { outBuf.put(indices.get(i - 2)); outBuf.put(indices.get(i % 2 == 0 ? i - 1 : i)); outBuf.put(indices.get(i % 2 == 0 ? i : i - 1)); @@ -890,11 +858,11 @@ public static void expandTriangleStrip(List indices, IntBuffer outBuf) } /** - * Defines a line segment representing the intersection of a line with and in the plane of a triangle. Used only - * within {@link #intersectTriangles}. + * Defines a line segment representing the intersection of a line with and + * in the plane of a triangle. Used only within {@link #intersectTriangles}. */ - protected static class TriangleIntersection - { + protected static class TriangleIntersection { + public Vec4 p0; // the first point of the line public Vec4 p1; // the second point of the line public double s0; // the distance along the line to the first intersection with the triangle @@ -904,15 +872,15 @@ protected static class TriangleIntersection /** * Intersects two triangles and returns their intersection vertices. * - * @param v the Cartesian coordinates of the first triangle. - * @param u the Cartesian coordinates of the second triangle. - * @param intersectionVertices a pre-allocated two-element array in which the intersection vertices, if any, are - * returned. + * @param v the Cartesian coordinates of the first triangle. + * @param u the Cartesian coordinates of the second triangle. + * @param intersectionVertices a pre-allocated two-element array in which + * the intersection vertices, if any, are returned. * - * @return -1 if there is no intersection, 1 if there is an intersection, or 0 if the triangles are co-planar. + * @return -1 if there is no intersection, 1 if there is an intersection, or + * 0 if the triangles are co-planar. */ - public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVertices) - { + public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVertices) { // Taken from http://jgt.akpeters.com/papers/Moller97/tritri.html#ISECTLINE // Compute plane equation of first triangle: n1 * x + d1 = 0. @@ -931,18 +899,23 @@ public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVert double du2 = n1.dot3(u[2]) + d1; // Coplanarity robustness check. - if (Math.abs(du0) < EPSILON) + if (Math.abs(du0) < EPSILON) { du0 = 0; - if (Math.abs(du1) < EPSILON) + } + if (Math.abs(du1) < EPSILON) { du1 = 0; - if (Math.abs(du2) < EPSILON) + } + if (Math.abs(du2) < EPSILON) { du2 = 0; + } double du0du1 = du0 * du1; double du0du2 = du0 * du2; if (du0du1 > 0 && du0du2 > 0) // same sign on all of them + != 0 ==> no intersection + { return -1; + } // Compute plane equation of second triangle: n2 * x + d2 = 0 e1x = u[1].x - u[0].x; @@ -960,18 +933,23 @@ public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVert double dv2 = n2.dot3(v[2]) + d2; // Coplanarity robustness check. - if (Math.abs(dv0) < EPSILON) + if (Math.abs(dv0) < EPSILON) { dv0 = 0; - if (Math.abs(dv1) < EPSILON) + } + if (Math.abs(dv1) < EPSILON) { dv1 = 0; - if (Math.abs(dv2) < EPSILON) + } + if (Math.abs(dv2) < EPSILON) { dv2 = 0; + } double dv0dv1 = dv0 * dv1; double dv0dv2 = dv0 * dv2; if (dv0dv1 > 0 && dv0dv2 > 0) // same sign on all of them + != 0 ==> no intersection + { return -1; + } // Compute direction of intersection line. Vec4 ld = n1.cross3(n2); @@ -981,13 +959,11 @@ public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVert int index = 0; double b = Math.abs(ld.y); double c = Math.abs(ld.z); - if (b > max) - { + if (b > max) { max = b; index = 1; } - if (c > max) - { + if (c > max) { index = 2; } @@ -999,8 +975,7 @@ public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVert double up0 = u[0].x; double up1 = u[1].x; double up2 = u[2].x; - if (index == 1) - { + if (index == 1) { vp0 = v[0].y; vp1 = v[1].y; vp2 = v[2].y; @@ -1008,9 +983,7 @@ public static int intersectTriangles(Vec4[] v, Vec4[] u, Vec4[] intersectionVert up0 = u[0].y; up1 = u[1].y; up2 = u[2].y; - } - else if (index == 2) - { + } else if (index == 2) { vp0 = v[0].z; vp1 = v[1].z; vp2 = v[2].z; @@ -1023,12 +996,12 @@ else if (index == 2) // Compute interval for triangle 1. TriangleIntersection isectA = compute_intervals_isectline(v, vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2); - if (isectA == null) + if (isectA == null) { return coplanarTriangles(n1, v, u) ? 0 : -1; + } int smallest1 = 0; - if (isectA.s0 > isectA.s1) - { + if (isectA.s0 > isectA.s1) { double cc = isectA.s0; isectA.s0 = isectA.s1; isectA.s1 = cc; @@ -1039,62 +1012,58 @@ else if (index == 2) TriangleIntersection isectB = compute_intervals_isectline(u, up0, up1, up2, du0, du1, du2, du0du1, du0du2); int smallest2 = 0; - if (isectB.s0 > isectB.s1) - { + if (isectB.s0 > isectB.s1) { double cc = isectB.s0; isectB.s0 = isectB.s1; isectB.s1 = cc; smallest2 = 1; } - if (isectA.s1 < isectB.s0 || isectB.s1 < isectA.s0) + if (isectA.s1 < isectB.s0 || isectB.s1 < isectA.s0) { return -1; + } // At this point we know that the triangles intersect: there's an intersection line, the triangles are not // coplanar, and they overlap. - - if (isectB.s0 < isectA.s0) - { - if (smallest1 == 0) + if (isectB.s0 < isectA.s0) { + if (smallest1 == 0) { intersectionVertices[0] = isectA.p0; - else + } else { intersectionVertices[0] = isectA.p1; + } - if (isectB.s1 < isectA.s1) - { - if (smallest2 == 0) + if (isectB.s1 < isectA.s1) { + if (smallest2 == 0) { intersectionVertices[1] = isectB.p1; - else + } else { intersectionVertices[1] = isectB.p0; - } - else - { - if (smallest1 == 0) + } + } else { + if (smallest1 == 0) { intersectionVertices[1] = isectA.p1; - else + } else { intersectionVertices[1] = isectA.p0; + } } - } - else - { - if (smallest2 == 0) + } else { + if (smallest2 == 0) { intersectionVertices[0] = isectB.p0; - else + } else { intersectionVertices[0] = isectB.p1; + } - if (isectB.s1 > isectA.s1) - { - if (smallest1 == 0) + if (isectB.s1 > isectA.s1) { + if (smallest1 == 0) { intersectionVertices[1] = isectA.p1; - else + } else { intersectionVertices[1] = isectA.p0; - } - else - { - if (smallest2 == 0) + } + } else { + if (smallest2 == 0) { intersectionVertices[1] = isectB.p1; - else + } else { intersectionVertices[1] = isectB.p0; + } } } @@ -1102,26 +1071,26 @@ else if (index == 2) } protected static TriangleIntersection compute_intervals_isectline(Vec4[] v, double vv0, double vv1, double vv2, - double d0, double d1, double d2, - double d0d1, double d0d2) - { + double d0, double d1, double d2, + double d0d1, double d0d2) { if (d0d1 > 0) // D0, D1 are on the same side, D2 on the other or on the plane + { return intersect(v[2], v[0], v[1], vv2, vv0, vv1, d2, d0, d1); - else if (d0d2 > 0) + } else if (d0d2 > 0) { return intersect(v[1], v[0], v[2], vv1, vv0, vv2, d1, d0, d2); - else if (d1 * d2 > 0 || d0 != 0) + } else if (d1 * d2 > 0 || d0 != 0) { return intersect(v[0], v[1], v[2], vv0, vv1, vv2, d0, d1, d2); - else if (d1 != 0) + } else if (d1 != 0) { return intersect(v[1], v[0], v[2], vv1, vv0, vv2, d1, d0, d2); - else if (d2 != 0) + } else if (d2 != 0) { return intersect(v[2], v[0], v[1], vv2, vv0, vv1, d2, d0, d1); - else + } else { return null; // triangles are coplanar + } } protected static TriangleIntersection intersect(Vec4 v0, Vec4 v1, Vec4 v2, double vv0, double vv1, double vv2, - double d0, double d1, double d2) - { + double d0, double d1, double d2) { TriangleIntersection intersection = new TriangleIntersection(); double tmp = d0 / (d0 - d1); @@ -1139,91 +1108,87 @@ protected static TriangleIntersection intersect(Vec4 v0, Vec4 v1, Vec4 v2, doubl return intersection; } - protected static boolean coplanarTriangles(Vec4 n, Vec4[] v, Vec4[] u) - { + protected static boolean coplanarTriangles(Vec4 n, Vec4[] v, Vec4[] u) { // First project onto an axis-aligned plane that maximizes the are of the triangles. int i0; int i1; - double[] a = new double[] {Math.abs(n.x), Math.abs(n.y), Math.abs(n.z)}; + double[] a = new double[]{Math.abs(n.x), Math.abs(n.y), Math.abs(n.z)}; if (a[0] > a[1]) // X > Y { - if (a[0] > a[2]) - { // X is greatest + if (a[0] > a[2]) { // X is greatest i0 = 1; i1 = 2; - } - else - { // Z is greatest + } else { // Z is greatest i0 = 0; i1 = 1; } - } - else // X < Y + } else // X < Y { - if (a[2] > a[1]) - { // Z is greatest + if (a[2] > a[1]) { // Z is greatest i0 = 0; i1 = 1; - } - else - { // Y is greatest + } else { // Y is greatest i0 = 0; i1 = 2; } } // Test all edges of triangle 1 against the edges of triangle 2. - double[] v0 = new double[] {v[0].x, v[0].y, v[0].z}; - double[] v1 = new double[] {v[1].x, v[1].y, v[1].z}; - double[] v2 = new double[] {v[2].x, v[2].y, v[2].z}; + double[] v0 = new double[]{v[0].x, v[0].y, v[0].z}; + double[] v1 = new double[]{v[1].x, v[1].y, v[1].z}; + double[] v2 = new double[]{v[2].x, v[2].y, v[2].z}; - double[] u0 = new double[] {u[0].x, u[0].y, u[0].z}; - double[] u1 = new double[] {u[1].x, u[1].y, u[1].z}; - double[] u2 = new double[] {u[2].x, u[2].y, u[2].z}; + double[] u0 = new double[]{u[0].x, u[0].y, u[0].z}; + double[] u1 = new double[]{u[1].x, u[1].y, u[1].z}; + double[] u2 = new double[]{u[2].x, u[2].y, u[2].z}; boolean tf = triangleEdgeTest(v0, v1, u0, u1, u2, i0, i1); - if (tf) + if (tf) { return true; + } tf = triangleEdgeTest(v1, v2, u0, u1, u2, i0, i1); - if (tf) + if (tf) { return true; + } tf = triangleEdgeTest(v2, v0, u0, u1, u2, i0, i1); - if (tf) + if (tf) { return true; + } // Finally, test whether one triangle is contained in the other one. tf = pointInTri(v0, u0, u1, u2, i0, i1); - if (tf) + if (tf) { return true; + } return pointInTri(u0, v0, v1, v2, i0, i1); } protected static boolean triangleEdgeTest(double[] v0, double[] v1, double[] u0, double[] u1, double[] u2, int i0, - int i1) - { + int i1) { double ax = v1[i0] - v0[i0]; double ay = v1[i1] - v0[i1]; // Test edge u0:u1 against v0:v1 boolean tf = edgeEdgeTest(v0, u0, u1, i0, i1, ax, ay); - if (tf) + if (tf) { return true; + } // Test edge u1:u2 against v0:v1 tf = edgeEdgeTest(v0, u1, u2, i0, i1, ax, ay); - if (tf) + if (tf) { return true; + } // Test edge u2:u0 against v0:v1 return edgeEdgeTest(v0, u2, u0, i0, i1, ax, ay); } - protected static boolean edgeEdgeTest(double[] v0, double[] u0, double[] u1, int i0, int i1, double ax, double ay) - { + protected static boolean edgeEdgeTest(double[] v0, double[] u0, double[] u1, int i0, int i1, double ax, double ay) { double bx = u0[i0] - u1[i0]; double by = u0[i1] - u1[i1]; double cx = v0[i0] - u0[i0]; @@ -1232,26 +1197,23 @@ protected static boolean edgeEdgeTest(double[] v0, double[] u0, double[] u1, int double f = ay * bx - ax * by; double d = by * cx - bx * cy; - if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f)) - { + if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f)) { double e = ax * cy - ay * cx; - if (f > 0) - { - if (e >= 0 && e <= f) + if (f > 0) { + if (e >= 0 && e <= f) { return true; - } - else - { - if (e <= 0 && e >= f) + } + } else { + if (e <= 0 && e >= f) { return true; + } } } return false; } - protected static boolean pointInTri(double[] v0, double[] u0, double[] u1, double[] u2, int i0, int i1) - { + protected static boolean pointInTri(double[] v0, double[] u0, double[] u1, double[] u2, int i0, int i1) { double a = u1[i1] - u0[i1]; double b = -(u1[i0] - u0[i0]); double c = -a * u0[i0] - b * u0[i1]; @@ -1270,8 +1232,7 @@ protected static boolean pointInTri(double[] v0, double[] u0, double[] u1, doubl return d0 * d1 > 0 && d0 * d2 > 0; } - public String toString() - { + public String toString() { return "Triangle (" + a + ", " + b + ", " + c + ")"; } } diff --git a/src/gov/nasa/worldwind/terrain/SectorGeometryList.java b/src/gov/nasa/worldwind/terrain/SectorGeometryList.java index 65fb268c26..e23cd94d6f 100644 --- a/src/gov/nasa/worldwind/terrain/SectorGeometryList.java +++ b/src/gov/nasa/worldwind/terrain/SectorGeometryList.java @@ -43,35 +43,38 @@ * @author tag * @version $Id: SectorGeometryList.java 1537 2013-08-07 19:58:01Z dcollins $ */ -public class SectorGeometryList extends ArrayList -{ - /** The spanning sector of all sector geometries contained in this list. */ +public class SectorGeometryList extends ArrayList { + + /** + * The spanning sector of all sector geometries contained in this list. + */ protected Sector sector; protected PickSupport pickSupport = new PickSupport(); protected HashMap> pickSectors = new HashMap>(); - /** Constructs an empty sector geometry list. */ - public SectorGeometryList() - { + /** + * Constructs an empty sector geometry list. + */ + public SectorGeometryList() { } /** - * Constructs a sector geometry list that contains a specified list of sector geometries. + * Constructs a sector geometry list that contains a specified list of + * sector geometries. * * @param list the secter geometries to place in the list. */ - public SectorGeometryList(SectorGeometryList list) - { + public SectorGeometryList(SectorGeometryList list) { super(list); } /** * Indicates the spanning sector of all sector geometries in this list. * - * @return a sector that is the union of all sectors of entries in this list. + * @return a sector that is the union of all sectors of entries in this + * list. */ - public Sector getSector() - { + public Sector getSector() { return sector; } @@ -80,69 +83,69 @@ public Sector getSector() * * @param sector the sector spanned by this list. */ - public void setSector(Sector sector) - { + public void setSector(Sector sector) { this.sector = sector; } /** - * Indicates that this list's sectors are about to be rendered. When rendering is complete, the {@link + * Indicates that this list's sectors are about to be rendered. When + * rendering is complete, the {@link * #endRendering(gov.nasa.worldwind.render.DrawContext)} must be called. * - * @param dc the current draw context. + * @param dc the current draw context. */ - public void beginRendering(DrawContext dc) - { - if (dc == null) - { + public void beginRendering(DrawContext dc) { + if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalStateException(message); } // TODO: add the beginRendering interface to Tessellator in order to eliminate this type test - if (dc.getGlobe().getTessellator() instanceof RectangularTessellator) + if (dc.getGlobe().getTessellator() instanceof RectangularTessellator) { ((RectangularTessellator) dc.getGlobe().getTessellator()).beginRendering(dc); + } } /** - * Restores state established by {@link #beginRendering(gov.nasa.worldwind.render.DrawContext)}. + * Restores state established by + * {@link #beginRendering(gov.nasa.worldwind.render.DrawContext)}. * * @param dc the current draw context. */ - public void endRendering(DrawContext dc) - { - if (dc == null) - { + public void endRendering(DrawContext dc) { + if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalStateException(message); } - if (dc.getGlobe().getTessellator() instanceof RectangularTessellator) + if (dc.getGlobe().getTessellator() instanceof RectangularTessellator) { ((RectangularTessellator) dc.getGlobe().getTessellator()).endRendering(dc); + } } /** - * Detects the locations of the sector geometries in this list that intersect a specified screen point. + * Detects the locations of the sector geometries in this list that + * intersect a specified screen point. *

      - * Note: Prior to calling this method, {@link #beginRendering(gov.nasa.worldwind.render.DrawContext)} must be + * Note: Prior to calling this method, + * {@link #beginRendering(gov.nasa.worldwind.render.DrawContext)} must be * called. * - * @param dc the current draw context. + * @param dc the current draw context. * @param pickPoint the screen point to test. */ - public void pick(DrawContext dc, java.awt.Point pickPoint) - { - if (dc == null) - { + public void pick(DrawContext dc, java.awt.Point pickPoint) { + if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalStateException(message); } - if (pickPoint == null) + if (pickPoint == null) { return; + } this.pickSupport.clearPickList(); this.pickSupport.beginPicking(dc); @@ -150,12 +153,10 @@ public void pick(DrawContext dc, java.awt.Point pickPoint) GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. gl.glShadeModel(GL2.GL_FLAT); - try - { + try { // render each sector in unique color this.beginRendering(dc); - for (SectorGeometry sector : this) - { + for (SectorGeometry sector : this) { Color color = dc.getUniquePickColor(); gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()); sector.render(dc); @@ -164,15 +165,13 @@ public void pick(DrawContext dc, java.awt.Point pickPoint) } PickedObject pickedSector = this.pickSupport.getTopObject(dc, pickPoint); - if (pickedSector == null || pickedSector.getObject() == null) + if (pickedSector == null || pickedSector.getObject() == null) { return; // no sector picked - + } this.beginSectorGeometryPicking(dc); SectorGeometry sector = (SectorGeometry) pickedSector.getObject(); sector.pick(dc, pickPoint); - } - finally - { + } finally { this.endSectorGeometryPicking(dc); this.endRendering(dc); gl.glShadeModel(GL2.GL_SMOOTH); // restore to default explicitly to avoid more expensive pushAttrib @@ -183,28 +182,29 @@ public void pick(DrawContext dc, java.awt.Point pickPoint) } /** - * Detects the locations of the sector geometries in this list that intersect any of the points in a specified list - * of screen points. + * Detects the locations of the sector geometries in this list that + * intersect any of the points in a specified list of screen points. *

      - * Note: Prior to calling this method, {@link #beginRendering(gov.nasa.worldwind.render.DrawContext)} must be + * Note: Prior to calling this method, + * {@link #beginRendering(gov.nasa.worldwind.render.DrawContext)} must be * called. * - * @param dc the current draw context. + * @param dc the current draw context. * @param pickPoints the points to test. * - * @return an array of picked objects that intersect one or more of the specified screen points. + * @return an array of picked objects that intersect one or more of the + * specified screen points. */ - public List pick(DrawContext dc, List pickPoints) - { - if (dc == null) - { + public List pick(DrawContext dc, List pickPoints) { + if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalStateException(message); } - if (pickPoints == null || pickPoints.size() < 1) + if (pickPoints == null || pickPoints.size() < 1) { return null; + } this.pickSupport.clearPickList(); this.pickSupport.beginPicking(dc); @@ -212,12 +212,10 @@ public List pick(DrawContext dc, List pickPoints) GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility. gl.glShadeModel(GL2.GL_FLAT); - try - { + try { // render each sector in a unique color this.beginRendering(dc); - for (SectorGeometry sector : this) - { + for (SectorGeometry sector : this) { Color color = dc.getUniquePickColor(); gl.glColor3ub((byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()); sector.render(dc); @@ -228,50 +226,46 @@ public List pick(DrawContext dc, List pickPoints) // Determine the sectors underneath the pick points. Assemble a pick-points per sector map. // Several pick points might intersect the same sector. this.pickSectors.clear(); - for (Point pickPoint : pickPoints) - { + for (Point pickPoint : pickPoints) { PickedObject pickedSector = this.pickSupport.getTopObject(dc, pickPoint); - if (pickedSector == null || pickedSector.getObject() == null) + if (pickedSector == null || pickedSector.getObject() == null) { continue; + } SectorGeometry sector = (SectorGeometry) pickedSector.getObject(); ArrayList sectorPickPoints; - if (!this.pickSectors.containsKey(sector)) - { + if (!this.pickSectors.containsKey(sector)) { sectorPickPoints = new ArrayList(); this.pickSectors.put(sector, sectorPickPoints); - } - else - { + } else { sectorPickPoints = this.pickSectors.get(sector); } sectorPickPoints.add(pickPoint); } - if (this.pickSectors.size() < 1) + if (this.pickSectors.size() < 1) { return null; + } // Now have each sector determine the pick position for each intersecting pick point. this.beginSectorGeometryPicking(dc); ArrayList pickedObjects = new ArrayList(); - for (Map.Entry> sector : this.pickSectors.entrySet()) - { + for (Map.Entry> sector : this.pickSectors.entrySet()) { ArrayList sectorPickPoints = sector.getValue(); PickedObject[] pos = sector.getKey().pick(dc, sectorPickPoints); - if (pos == null) + if (pos == null) { continue; + } - for (PickedObject po : pos) - { - if (po != null) + for (PickedObject po : pos) { + if (po != null) { pickedObjects.add(po); + } } } return pickedObjects; - } - finally - { + } finally { this.endSectorGeometryPicking(dc); this.endRendering(dc); gl.glShadeModel(GL2.GL_SMOOTH); // restore to default explicitly to avoid more expensive pushAttrib @@ -282,14 +276,15 @@ public List pick(DrawContext dc, List pickPoints) } /** - * Indicates that sector geometry picking is about to be performed. Configures the state necessary to correctly draw - * sector geometry in a second pass using unique per-triangle colors. When picking is complete, {@link - * #endSectorGeometryPicking(gov.nasa.worldwind.render.DrawContext)} must be called. + * Indicates that sector geometry picking is about to be performed. + * Configures the state necessary to correctly draw sector geometry in a + * second pass using unique per-triangle colors. When picking is complete, {@link + * #endSectorGeometryPicking(gov.nasa.worldwind.render.DrawContext)} must be + * called. * * @param dc the current draw context. */ - protected void beginSectorGeometryPicking(DrawContext dc) - { + protected void beginSectorGeometryPicking(DrawContext dc) { GL gl = dc.getGL(); gl.glDepthFunc(GL.GL_LEQUAL); @@ -298,8 +293,7 @@ protected void beginSectorGeometryPicking(DrawContext dc) // color geometry's depth values toward the eye and disable depth buffer writes. This works around an issue // where the VMware driver breaks OpenGL's invariance requirement when per-vertex colors are enabled. // See WWJ-425. - if (dc.getGLRuntimeCapabilities().isVMwareSVGA3D()) - { + if (dc.getGLRuntimeCapabilities().isVMwareSVGA3D()) { gl.glDepthMask(false); gl.glEnable(GL.GL_POLYGON_OFFSET_FILL); gl.glPolygonOffset(-1f, -1f); @@ -307,18 +301,17 @@ protected void beginSectorGeometryPicking(DrawContext dc) } /** - * Restores state established by {@link #beginSectorGeometryPicking(gov.nasa.worldwind.render.DrawContext)}. + * Restores state established by + * {@link #beginSectorGeometryPicking(gov.nasa.worldwind.render.DrawContext)}. * * @param dc the current draw context. */ - protected void endSectorGeometryPicking(DrawContext dc) - { + protected void endSectorGeometryPicking(DrawContext dc) { GL gl = dc.getGL(); gl.glDepthFunc(GL.GL_LESS); // restore to default explicitly to avoid more expensive pushAttrib - if (dc.getGLRuntimeCapabilities().isVMwareSVGA3D()) - { + if (dc.getGLRuntimeCapabilities().isVMwareSVGA3D()) { gl.glDepthMask(true); gl.glDisable(GL.GL_POLYGON_OFFSET_FILL); gl.glPolygonOffset(0f, 0f); @@ -326,16 +319,18 @@ protected void endSectorGeometryPicking(DrawContext dc) } /** - * Computes a Cartesian point at a specified latitude, longitude and altitude above the terrain. + * Computes a Cartesian point at a specified latitude, longitude and + * altitude above the terrain. * - * @param position the position to compute the Cartesian point for. The altitude element of the position is - * considered to be distance above the terrain at the position's latitude and longitude. + * @param position the position to compute the Cartesian point for. The + * altitude element of the position is considered to be distance above the + * terrain at the position's latitude and longitude. * - * @return the Cartesian point, in meters, relative to an origin of (0, 0, 0). Will be null if there is no sector - * geometry in this list for the specifed latitude and longitude. + * @return the Cartesian point, in meters, relative to an origin of (0, 0, + * 0). Will be null if there is no sector geometry in this list for the + * specifed latitude and longitude. */ - public Vec4 getSurfacePoint(Position position) - { + public Vec4 getSurfacePoint(Position position) { return this.getSurfacePoint(position.getLatitude(), position.getLongitude(), position.getElevation()); } @@ -344,55 +339,55 @@ public Vec4 getSurfacePoint(Position position) * * @param latLon the location of the point to compute. * - * @return the Cartesian point, in meters, relative to an origin of (0, 0, 0). Will be null if there is no sector - * geometry in this list for the specifed latitude and longitude. + * @return the Cartesian point, in meters, relative to an origin of (0, 0, + * 0). Will be null if there is no sector geometry in this list for the + * specifed latitude and longitude. */ - public Vec4 getSurfacePoint(LatLon latLon) - { + public Vec4 getSurfacePoint(LatLon latLon) { return this.getSurfacePoint(latLon.getLatitude(), latLon.getLongitude(), 0d); } /** * Computes a Cartesian point at a specified location on the terrain. * - * @param latitude the latitude of the point to compute. + * @param latitude the latitude of the point to compute. * @param longitude the longitude of the point to compute. * - * @return the Cartesian point, in meters, relative to an origin of (0, 0, 0). Will be null if there is no sector - * geometry in this list for the specifed latitude and longitude. + * @return the Cartesian point, in meters, relative to an origin of (0, 0, + * 0). Will be null if there is no sector geometry in this list for the + * specifed latitude and longitude. */ - public Vec4 getSurfacePoint(Angle latitude, Angle longitude) - { + public Vec4 getSurfacePoint(Angle latitude, Angle longitude) { return this.getSurfacePoint(latitude, longitude, 0d); } /** - * Computes a Cartesian point at a specified latitude, longitude and altitude above the terrain. + * Computes a Cartesian point at a specified latitude, longitude and + * altitude above the terrain. * - * @param latitude the latitude of the point to compute. - * @param longitude the longitude of the point to compute. - * @param metersOffset the distance above the terrain of the point to compute. + * @param latitude the latitude of the point to compute. + * @param longitude the longitude of the point to compute. + * @param metersOffset the distance above the terrain of the point to + * compute. * - * @return the Cartesian point, in meters, relative to an origin of (0, 0, 0). Will be null if there is no sector - * geometry in this list for the specifed latitude and longitude. + * @return the Cartesian point, in meters, relative to an origin of (0, 0, + * 0). Will be null if there is no sector geometry in this list for the + * specifed latitude and longitude. */ - public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset) - { - if (latitude == null || longitude == null) - { + public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset) { + if (latitude == null || longitude == null) { String msg = Logging.getMessage("nullValue.LatLonIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } - for (int i = 0; i < this.size(); i++) - { + for (int i = 0; i < this.size(); i++) { SectorGeometry sg = this.get(i); - if (sg.getSector().contains(latitude, longitude)) - { + if (sg.getSector().contains(latitude, longitude)) { Vec4 point = sg.getSurfacePoint(latitude, longitude, metersOffset); - if (point != null) + if (point != null) { return point; + } } } @@ -402,15 +397,14 @@ public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset /** * Determines if and where a ray intersects the geometry. * - * @param line the Line for which an intersection is to be found. + * @param line the Line for which an intersection is to be + * found. * - * @return the <Vec4> point closest to the ray origin where an intersection has been found or null if no - * intersection was found. + * @return the <Vec4> point closest to the ray origin where an + * intersection has been found or null if no intersection was found. */ - public Intersection[] intersect(Line line) - { - if (line == null) - { + public Intersection[] intersect(Line line) { + if (line == null) { String msg = Logging.getMessage("nullValue.LineIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); @@ -420,31 +414,34 @@ public Intersection[] intersect(Line line) Intersection[] hits; ArrayList list = new ArrayList(); - for (SectorGeometry sg : sglist) - { - if (sg.getExtent().intersects(line)) - if ((hits = sg.intersect(line)) != null) + for (SectorGeometry sg : sglist) { + if (sg.getExtent().intersects(line)) { + if ((hits = sg.intersect(line)) != null) { list.addAll(Arrays.asList(hits)); + } + } } int numHits = list.size(); - if (numHits == 0) + if (numHits == 0) { return null; + } hits = new Intersection[numHits]; list.toArray(hits); final Vec4 origin = line.getOrigin(); - Arrays.sort(hits, new Comparator() - { - public int compare(Intersection i1, Intersection i2) - { - if (i1 == null && i2 == null) + Arrays.sort(hits, new Comparator() { + public int compare(Intersection i1, Intersection i2) { + if (i1 == null && i2 == null) { return 0; - if (i2 == null) + } + if (i2 == null) { return -1; - if (i1 == null) + } + if (i1 == null) { return 1; + } Vec4 v1 = i1.getIntersectionPoint(); Vec4 v2 = i2.getIntersectionPoint(); @@ -457,23 +454,26 @@ public int compare(Intersection i1, Intersection i2) } /** - * Determines if and where the geometry intersects the ellipsoid at a given elevation. + * Determines if and where the geometry intersects the ellipsoid at a given + * elevation. *

      - * The returned array of Intersection describes a list of individual segments - two - * Intersection for each, corresponding to each geometry triangle that intersects the given elevation. + * The returned array of Intersection describes a list of + * individual segments - two Intersection for each, + * corresponding to each geometry triangle that intersects the given + * elevation. *

      - * Note that the provided bounding Sector only serves as a 'hint' to avoid processing unnecessary - * geometry tiles. The returned intersection list may contain segments outside that sector. + * Note that the provided bounding Sector only serves as a + * 'hint' to avoid processing unnecessary geometry tiles. The returned + * intersection list may contain segments outside that sector. * * @param elevation the elevation for which intersections are to be found. - * @param sector the sector inside which intersections are to be found. + * @param sector the sector inside which intersections are to be found. * - * @return a list of Intersection pairs/segments describing a contour line at the given elevation. + * @return a list of Intersection pairs/segments describing a + * contour line at the given elevation. */ - public Intersection[] intersect(double elevation, Sector sector) - { - if (sector == null) - { + public Intersection[] intersect(double elevation, Sector sector) { + if (sector == null) { String message = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); @@ -483,16 +483,18 @@ public Intersection[] intersect(double elevation, Sector sector) Intersection[] hits; ArrayList list = new ArrayList(); - for (SectorGeometry sg : sglist) - { - if (sector.intersects(sg.getSector())) - if ((hits = sg.intersect(elevation)) != null) + for (SectorGeometry sg : sglist) { + if (sector.intersects(sg.getSector())) { + if ((hits = sg.intersect(elevation)) != null) { list.addAll(Arrays.asList(hits)); + } + } } int numHits = list.size(); - if (numHits == 0) + if (numHits == 0) { return null; + } hits = new Intersection[numHits]; list.toArray(hits);