/**
     * WMSTestSupport hook called after the system (ie spring context) has been
     * fully initialized. Adds JOG GeoPackage to the raster layers.
     *
     * @param testData
     * @throws Exception
     */


/**
     * Smoke test to make sure the page structure was correctly set up.
     */


/**
     * Asks this map producer to create a map image for the passed
     * {@linkPlain WMSMapContext}, which contains enough information for doing
     * such a process. Typically invoked by WMS GetMap.
     *
     * @param mapContent
     * @return
     *
     * @throws ServiceException
     * @throws IOException
     */


/**
     * Returns the zoom level, plus one, closest to the highest resolution
     * coverage used in the map request. This is the ending value used in loops
     * that process the levels, it is not the max zoom level in the GeoPackage.
     *
     * Overrides the base class behavior which returned a "zoom level + 1" where
     * the zoom level contained at least 256 tiles.
     *
     * @param gridSubset the grid for the GeoPackage
     * @param minZoom the starting zoom level
     * @param request the map request containing the layer coverages
     * @return the selected maximum zoom level + 1
     */


/**
     * Writes out the map's image to a byte array that is compatible with
     * ImageIO.read
     *
     * @param map
     * @return
     * @throws IOException
     */


/**
     * Special method to add tiles using Geopackage's own grid matrix system
     * rather than GWC gridsubsets
     *
     * @param tiles
     * @param mapLayers
     * @param map
     * @throws IOException
     * @throws ServiceException
     */


/**
     * Returns true if the string is a valid SQLite identifier.
     *
     * @param string Text to be evaluated
     * @return True if the text consists solely of alphanumeric or underscore
     * characters, does not start with a digit and is not a keyword.
     */


/**
     * Returns true if the string matches an SQLite keyword.
     *
     * @param string To be evaluated
     * @return True if the text matches a keyword
     */


/**
     * Decodes the parameter from an external source or input stream to a
     * GeoPackageProcessRequest. This decode method is used when a
     * SimpleInputProvider is used via the unit tests.
     *
     * @param input an input stream
     * @return a GeoPackageProcessRequest
     * @throws Exception
     */


/**
     * Decodes the parameter from an external source that has been pre-parsed.
     * <p>
     * This method should transform the object from the external representation
     * to the internal representation: a GeoPackageProcessRequest.
     * </p>
     *
     * @param input An object from the XML parser
     * @return a GeoPackageProcessRequest
     * @throws Exception
     */


/**
     * Creates a folder with a arbitrary name under the given parent folder.
     *
     * @param baseDir parent folder
     * @return a new folder
     */


/**
     * Executes a request to generate a GeoPackage via a WPS request.
     *
     * GeoServer WPS Demo can generate a request using the gs:GeoPackage
     * selection.
     *
     * @param contents The parsed
     * {@code <geopackage xmlns="http://www.opengis.net/gpkg" />} contents
     * @return A link to the generated GeoPackage, e.g.,
     * {@code  http://host:port/geoserver/ows?service=WPS&version=1.0.0&request=GetExecutionResult&executionId=<xxx>&outputId=<outputName>&mimetype=application/x-gpkg}
     *
     * @throws IOException
     */


/**
     * Sets up the output response popup window.
     */


/**
     * Sets up the XML popup window.
     */


/**
     * Initializes the geopackage database.
     * <p>
     * This method creates all the necessary metadata tables.
     * </p>
     */


/**
     * Initializes a geopackage connection.
     * <p>
     * This method creates all the necessary metadata tables.
     * </p>
     */


/**
     * Closes the geopackage database connection.
     * <p>
     * The application should always call this method when done with a
     * geopackage to prevent connection leakage.
     * </p>
     */


/**
     * Adds an EPSG CRS to the GeoPackage - with long/lat ordering - registering
     * it in the spatial_ref_sys table.
     *
     * This method will look up the {@code srid} in the local EPSG database. Use
     * {@link #addCRS(CoordinateReferenceSystem, int)} to specify an explicit
     * CRS, authority, code entry.
     *
     * @param srid
     */


/**
     * Adds a crs to the geopackage, registering it in the spatial_ref_sys
     * table.
     *
     * @param crs The crs to add.
     * @param auth The authority code, example: epsg
     * @param srid The spatial reference system id.
     *
     */


/**
     * Returns list of contents of the geopackage.
     */


/**
     * Lists all the feature entries in the geopackage.
     *
     */


/**
     * Looks up a feature entry by name.
     *
     * @param name THe name of the feature entry.
     * @return The entry, or null if no such entry exists.
     */


/**
     * Creates a new feature entry in the geopackage.
     * <p>
     * The resulting feature dataset will be empty. The
     * {@link #writer(FeatureEntry, boolean, Transaction)} method returns a
     * writer object that can be used to populate the dataset.
     * </p>
     *
     * @param entry Contains metadata about the feature entry.
     * @param schema The schema of the feature dataset.
     *
     * @throws IOException Any errors occurring while creating the new feature
     * entry.
     */


/**
     * Adds a new feature dataset to the geopackage.
     *
     * @param entry Contains metadata about the feature entry.
     * @param collection The simple feature collection to add to the geopackage.
     *
     * @throws IOException Any errors occurring while adding the new feature
     * dataset.
     */


/**
     * Adds a new feature dataset to the geopackage.
     *
     * @param entry Contains metadata about the feature entry.
     * @param source The dataset to add to the geopackage.
     * @param filter Filter specifying what subset of feature dataset to
     * include, may be null to specify no filter.
     *
     * @throws IOException Any errors occurring while adding the new feature
     * dataset.
     */


/**
     * Returns a writer used to modify or add to the contents of a feature
     * dataset.
     *
     * @param entry The feature entry.
     * @param append Flag controlling whether to modify existing contents, or
     * append to the dataset.
     * @param filter Filter determining what subset of dataset to modify, only
     * relevant when
     * <tt>append</tt> set to false. May be null to specify no
     * filter.
     * @param tx Transaction object, may be null to specify auto
     * commit transaction.
     *
     */


/**
     * Returns a reader for the contents of a feature dataset.
     *
     * @param entry The feature entry.
     * @param filter Filter Filter determining what subset of dataset to return.
     * May be null to specify no filter.
     * @param tx Transaction object, may be null to specify auto
     * commit transaction.
     */


/**
     * Create a spatial index
     *
     * @param e feature entry to create spatial index for
     */


/**
     * Queries the gpkg_contents table. For each entry queries the
     *
     * @return
     * @throws IOException
     */


/**
     * Looks up a tile entry by name.
     *
     * @param name The name of the tile entry.
     * @return The entry, or null if no such entry exists.
     */


/**
     * Creates a new tile entry in the geopackage.
     *
     * @param entry The tile entry.
     */


/**
     * Adds a tile to the geopackage.
     *
     * @param entry The tile metadata entry.
     * @param tile The tile.
     */


/**
     * Retrieve tiles within certain zooms and column/row boundaries
     *
     * @param entry the tile entry
     * @param lowZoom low zoom boundary
     * @param highZoom high zoom boundary
     * @param lowCol low column boundary
     * @param highCol high column boundary
     * @param lowRow low row boundary
     * @param highRow high row boundary
     * @return
     * @throws IOException
     */


/**
     * Verifies if a spatial index is present
     *
     * @param entry The feature entry.
     * @return whether this feature entry has a spatial index available.
     * @throws IOException
     */


/**
     * Searches a spatial index.
     *
     * @param entry The feature entry.
     * @param minX Optional minimum x boundary.
     * @param minY Optional minimum y boundary.
     * @param maxX Optional maximum x boundary.
     * @param maxY Optional maximum y boundary.
     */


/**
     *
     * @param rs Result set containing a row from the gpkg_contents table
     * @param cx Connection to the GeoPackage
     * @param zoom zoom level
     * @return new int[] {minCol, minRow, maxCol, maxRow}
     * @throws IOException
     */


/**
     * Returns the tile matrix information for the specified raster data table
     * (supplied the ResultSet param) from the gpkg_tile_matrix table. Creates a
     * TileMatix object for each row in the gpkg_tile_matrix table for the
     * specifed table.
     *
     * @param rs Result set containing a row from the gpkg_contents table
     * @param cx Connection to the GeoPackage
     * @return a new TileEntry object containing a TileMatrix collection that
     * represents the specified table.
     * @throws SQLException
     * @throws IOException
     */


/**
     * Initializes the given Entry object from a row in the gpkg_contents table.
     *
     * @param e Entry object to be initialized from the
     * @param rs Result set containing a row from the gpkg_contents table
     * @throws SQLException
     * @throws IOException
     */


/**
     * @param bytes
     * @param factory
     * @return
     * @throws IOException
     */


/*
     * OptimizedGeoPackageBinary {
     * byte[3] magic = 0x47504230; // 'GPB'
     * byte flags;                 // see flags layout below
     * unit32 srid;
     * double[] envelope;          // see flags envelope contents indicator code below
     * WKBGeometry geometry;       // per OGC 06-103r4 clause 8
     *
     *
     * flags layout:
     *   bit     7       6       5       4       3       2       1       0
     *   use     -       -       X       Y       E       E       E       B

     *   use:
     *   X: GeoPackageBinary type (0: StandardGeoPackageBinary, 1: ExtendedGeoPackageBinary)
     *   Y: 0: non-empty geometry, 1: empty geometry
     *
     *   E: envelope contents indicator code (3-bit unsigned integer)
     *     value |                    description                               | envelope length (bytes)
     *       0   | no envelope (space saving slower indexing option)            |      0
     *       1   | envelope is [minx, maxx, miny, maxy]                         |      32
     *       2   | envelope is [minx, maxx, miny, maxy, minz, maxz]             |      48
     *       3   | envelope is [minx, maxx, miny, maxy, minm, maxm]             |      48
     *       4   | envelope is [minx, maxx, miny, maxy, minz, maxz, minm, maxm] |      64
     *   B: byte order for header values (1-bit Boolean)
     *       0 = Big Endian   (most significant bit first)
     *       1 = Little Endian (least significant bit first)
     */


/**
     * Tests if the source appears to be a valid GeoPackage file.
     *
     * @param source a File, String, URL or FileImageInputStreamExtImpl object
     * @return true if the source object references an existing GeoPackage file
     *
     */


/**
     * Opens the GeoPackage raster file and obtains the coverage names used for
     * the image index.
     *

     * This method has to be called before any data access, in order to already
     * have the native raster data metadata available.
     *

     *
     * @return true if everything is consistent
     * @throws IIOException
     */


/**
     * Returns if the given image is tiled (true for all raster GeoPackages).
     *
     * @param imageIndex ignored
     * @return true
     * @throws IOException
     */


/**
     * Returns a BufferedImage defined by the values in the supplied
     * ImageReadParam.
     *
     * @param imageIndex the image index (mapped to a zoom level)
     * @param param
     * @return A BufferedImage containing the tile data from a GeoPackage
     * @throws IOException
     */


/**
     * Reads the tile indicated by the tileX and tileY
     * arguments, returning it as a BufferedImage. If the arguments
     * are out of range, an IllegalArgumentException is thrown.
     *
     * @param imageIndex the image index (mapped to a zoom level)
     * @param tileX
     * @param tileY
     * @return
     * @throws IOException
     */


/**
     * Resets this {@link GeoPackageImageReader}.
     */


/**
     * Ensure the given coverage name matches a user-data table name in the
     * GeoPackage.
     *
     * @param coverageName the name to validate
     * @return true if the name matches a user-data table name in the
     * {@link GeoPackage}
     */


/**
     * Returns the {@link OverviewPolicy} found in this reader's hints.
     *
     * @return the {@link OverviewPolicy} in the hints; or if not found, the
     * {@code OverviewPolicy.getDefaultPolicy()} (NEAREST)
     */


/**
     * Returns a zoom level for the specified coverage matching the given
     * overview policy and requested resolution.
     *
     * @param coverageName the raster coverage name
     * @param policy the overview policy governing the zoom level selection
     * @param requestedRes two-element array defining the requested resolution:
     * [xRes, yRes]
     * @return the best zoom level for the specified overview policy and
     * resolution
     */


/**
     * Called by setReadParam, this method is responsible for evaluating
     * possible subsampling factors once the best resolution level has been
     * found, in case we have support for overviews, or starting from the
     * original coverage in case there are no overviews available.
     *
     * Copied from base class decimationOnReadingControl and fixed for
     * multi-coverage GeoPackage format: i.e., getHighestRes(coverageName)
     *
     * @param coverageName
     * @param imageIndex zero-based image index (0 is highest resolution)
     * @param readParams
     * @param requestedRes
     */


/**
     * divideWithTolerance will round result if remainder is withing tolerance,
     * otherwise it truncates the result.
     *
     * @param dividend
     * @param divisor
     * @param tolerance
     * @return
     */


/**
     * Creates a {@link GridCoverage} for the provided {@link PlanarImage} using
     * the {@link #raster2Model} that was provided for this coverage.
     *
     *
     * @param coverageName
     * @param image contains the data for the coverage to create.
     * @param raster2Model is the {@link MathTransform} that maps from the
     * raster space to the model space.
     * @return a {@link GridCoverage}
     * @throws IOException
     */


/**
     * Reads the raster tile data intersecting the given region within the
     * specified coverage's zoom level into a {@link BufferedImage}.
     *
     * @param coverageName the raster coverage name
     * @param zoomLevel the zoom level to read
     * @param region requested pixel region within the tileset
     * @param inputTransparentColor color to use for transparency; may be null
     * @return a {@link BufferedImage} matching the region's width and height
     * @throws IllegalArgumentException
     * @throws IOException
     */


/**
     * Reads the raster tile data into a BufferedImage.
     *
     * @param coverageName
     * @param zoomLevel
     * @param startCol
     * @param endCol
     * @param startRow
     * @param endRow
     * @param inputTransparentColor
     * @return
     * @throws IOException
     */


/**
     * Maybe used by GeoPackageImageReader.readTile().
     *
     * @param zoomLevel
     * @param tileX a matrix tile index
     * @param tileY a matrix tile index
     * @return A BufferedImage containing the specified tile
     * @throws java.io.IOException
     */


/**
     * Creates a BufferedImage from the supplied image data byte array.
     *
     * @param data A byte array containing image data
     * @return A new BufferedImage
     * @throws IOException
     */


/**
     * Creates a transparent image suitable for rendering tiles into.
     *
     * @param width The width of the new image
     * @param height The height of the new image
     * @param inputTransparentColor
     * @return A new BufferedImage with transparent fill.
     */


/**
     * Creates an image matching a source image's color model and properties.
     *
     * @param copyFrom The source image
     * @param width The width of the new image
     * @param height The height of the new image
     * @return A new BufferedImage matching the source image's color model and
     * properties
     */


/**
         * Allows equality test of members by subclasses.
         */


/**
         * Encodes a GeoPackageProcessRequest object as XML.
         *
         * @param o a GeoPackageProcessRequest object
         * @throws IllegalArgumentException
         */


/**
         * Encodes a GeoPackageProcessRequest object as XML.
         *
         * @param request The GeoPackageProcessRequest to encode
         * @param mainProcess
         */


/**
         * Helper to build a set of attributes out of a list of key/value pairs
         *
         * @param nameValues
         */


/**
         * Appends the wps:DataInputs containing the geopackage element.
         *
         * @param request
         */


/**
         * Append the geopackage element.
         *
         * @param request
         */


/**
         * Appends the wps:ResponseForm contents.
         */


/**
     * Registers the bindings for the configuration.
     *
     * @generated
     */


/**
     * SQLite's LIKE is usually case insensitive - there are many possible "fixes" out there
     * but all are hard to implement or seem not to work for all CharacterSets.
     */


/**
     * Test of init method, of class TileEntry.
     */


/**
     * Test of setMinZoomLevel method, of class TileEntry.
     */


/**
     * Test of setMaxZoomLevel method, of class TileEntry.
     */


/**
     * Test of setTileMatrixSetBounds method, of class TileEntry.
     */


/**
     * Test of setTileMatricies method, of class TileEntry.
     */


/**
     * Test of getTileMatricies method, of class TileEntry.
     */


/**
     * Test of getTileMatrix method, of class TileEntry.
     */


/**
     * Test of getTileMatrixSetBounds method, of class TileEntry.
     */


/**
     * Test of getMaxZoomLevel method, of class TileEntry.
     */


/**
     * Test of getMinZoomLevel method, of class TileEntry.
     */


/**
     * Test of getCrs method, of class TileEntry.
     */


/**
     * Identical to {@link GeoPackageTest#testCreateFeatureEntry()} but uses a
     * pattern which requires quotes in SQLite.
     *
     * @throws Exception
     */


/**
     * Identical to {@link GeoPackageTest#testSpatialIndexReading()} but uses a
     * pattern which requires quotes in SQLite.
     *
     * @throws Exception
     */


/**
     * Identical to {@link GeoPackageTest#testCreateTileEntry()} but uses a
     * pattern which requires quotes in SQLite.
     *
     * @throws Exception
     */


//Since we can't have multiple geom columns use multiple tables instead.


/**
     * Test of getDescription method, of class GeoPackageImageReaderSpi.
     */


/**
     * Test of canDecodeInput method, of class GeoPackageImageReaderSpi.
     * @throws java.lang.Exception
     */


/**
     * Test of createReaderInstance method, of class GeoPackageImageReaderSpi.
     * @throws java.lang.Exception
     */


/**
     * Test of getReader method, of class GeoPackageFormat.
     */


/**
     * Test of getWriter method, of class GeoPackageFormat.
     */


/**
     * Test of accepts method, of class GeoPackageFormat.
     */


/**
     * Test of accepts method, of class GeoPackageFormat.
     * @throws java.io.IOException
     */


/**
     * Test of getDefaultImageIOWriteParameters method, of class
     * GeoPackageFormat.
     */


/**
     * Test of getFileFromSource method, of class GeoPackageFormat.
     */


/**
     * Test that a GeoPackageProcessRequest can be converted to XML correctly.
     */


/**
     * Test of hashCode method, of class GeoPackageProcessRequest.
     */


/**
     * Test of equals method, of class GeoPackageProcessRequest.
     */


/**
     * Test of addLayer method, of class GeoPackageProcessRequest.
     */


/**
     * Test of getLayer method, of class GeoPackageProcessRequest.
     */


/**
     * Test of getLayerCount method, of class GeoPackageProcessRequest.
     */


/**
     * Test of getName method, of class GeoPackageProcessRequest.
     */


/**
     * Test of setName method, of class GeoPackageProcessRequest.
     */


/**
     * Test of getPath method, of class GeoPackageProcessRequest.
     */


/**
     * Test of setPath method, of class GeoPackageProcessRequest.
     */


/**
     * Test of getRemove method, of class GeoPackageProcessRequest.
     */


/**
     * Test of setRemove method, of class GeoPackageProcessRequest.
     */


/**
     * Perform the equality check in its own method so that one can more easily
     * debug. Set a breakpoint at the println, then drop-to-frame and re-run the
     * call to equals.
     */


/**
     * Fetch the config from the model metadata file located on the server,
     * downloading/updating the file cache as needed. This method does not
     * return null but throws an exception if it fails to load the model
     * metadata.
     *
     * @param name of the model metadata object in the file
     * @param url from which to download/load the metadata
     * @return the config
     */


/**
     * This function is called when the GS manager starts your apk.
     * Put all of your start up code in here.
     */


/**
     * This function is called when the GS manager stops your apk.
     * Put all of your clean up code in here. You should also call the terminate helper function
     * at the very end of this function.
     */


/**
     * This function is called when the GS manager sends a custom command to your apk.
     * Please handle your commands in this function.
     *
     * @param command
     */


/** Return a byte array representing the compressed sequence
      [data[begin]; data[end-1]] */


/** Return an array containing the number sequence decompressed from data. */


/** Checks the object for internal consistency. If a problem is detected,
      an IllegalArgumentException is thrown. */


/** Returns an internal representation of the interval a number belongs to.
      @param val number whose interval is requested
      @return interval number, starting with -1 (smaller than all numbers in the
      RangeSet), 0 (first "on" interval), 1 (first "off" interval etc.), up to
      (and including) sz-1 (larger than all numbers in the RangeSet). */


/** Append a range to the object.
      @param a first long in range
      @param b one-after-last long in range */


/** Append an entire range set to the object. */


/** Estimate a good strategy for set operations involving two RangeSets. */


/** Internal helper function for constructing unions, intersections
      and differences of two RangeSets. */


/** Returns true if all numbers [a;b[ are contained in the set, else false. */


/** Returns true if any of the numbers [a;b[ are contained in the set,
      else false. */


/** @return total number of values (not ranges) in the set. */


/** Internal helper function for building unions and differences of the
      RangeSet with a single range. */


/** After this operation, the RangeSet contains the intersection of itself and
      [a;b[. */


/** Creates an array containing all the numbers in the RangeSet.
      Not recommended, because the arrays can become prohibitively large.
      It is preferrable to use a ValueIterator or explicit loops. */


/** Returns a ValueIterator, which iterates over all individual numbers
      in the RangeSet. */


/** This method calculates the arc tangent of y/x in radians, using
      the signs of the two arguments to determine the quadrant of the
      result. The results may have maximum error of 2 ulps. */


/** Returns the arc tangent of an angle. The results may have
      maximum error of 2 ulps. */


/** Returns the trigonometric sine of an angle. The results may
      have maximum error of 2 ulps. */


/** Returns the trigonometric cosine of an angle. The results may
      have maximum error of 2 ulps. */


/** Parses a string following either the basic ASCII or JSON syntax given in
      the MOC standard document, and converts it into a MOC.
      The string need not obey the rules for a well-formed MOC given in the
      document. */


/** Normalize the vector */


/** Return normalized vector */


/** Converts the map from NESTED to RING scheme or vice versa.
      This operation is done in-place, i.e. it does not require additional
      memory. */


/** Imports the map "orig" to this object, adjusting pixel ordering.
      @param orig map to import */


/** Imports the map "orig" to this object, adjusting pixel ordering
      and increasing resolution.
      @param orig map to import */


/** Imports the map "orig" to this object, adjusting pixel ordering
      and reducing resolution.
      @param orig map to import
      @param pessimistic if true, set a pixel to undefined if at least one the
        original subpixels was undefined; otherwise only set it to undefined if
        all original subpixels were undefined. */


/** Imports the map "orig" to this object, adjusting pixel ordering
      and resolution if necessary.
      @param orig map to import
      @param pessimistic only used when resolution must be reduced: if true,
        set a pixel to undefined if at least one the original subpixels
        was undefined; otherwise only set it to undefined if all original
        subpixels were undefined. */


/** Integer square root.
      @param arg
      @return the integer {@code n} which fulfills {@code n^2<=arg<(n+1)^2} */


/** Computes the cosine of the angular distance between two z, phi positions
      on the unit sphere. */


/** Returns the remainder of the division {@code v1/v2}.
      The result is non-negative.
      @param v1 dividend; can be positive or negative
      @param v2 divisor; must be positive
      @return remainder of the division; positive and smaller than {@code v2} */


/** Calculates the map order from its Nside parameter.
      @param nside the Nside parameter
      @return the map order corresponding to {@code nside}; -1 if
        {@code nside} is not a power of 2. */


/** Calculates the Nside parameter from the number of pixels.
      @param npix the number of pixels
      @return the computed Nside parameter */


/** Calculates the number of pixels from the Nside parameter.
      @param nside the Nside parameter
      @return the computed number of pixels */


/** Calculates the number of pixels from the order parameter.
      @param order the order parameter
      @return the computed number of pixels */


/** Returns nested pixel number for the supplied ring pixel number.
      @param ipring the requested pixel number in RING scheme.
      @return the corresponding pixel number in NESTED scheme. */


/** Returns ring pixel number for the supplied nested pixel number.
      @param ipnest the requested pixel number in NESTED scheme.
      @return the corresponding pixel number in RING scheme. */


/** Returns the neighboring pixels of ipix.
      This method works in both RING and NEST schemes, but is
      considerably faster in the NEST scheme.
      @param ipix the requested pixel number.
      @return array with indices of the neighboring pixels.
        The returned array contains (in this order)
        the pixel numbers of the SW, W, NW, N, NE, E, SE and S neighbor
        of ipix. If a neighbor does not exist (this can only happen
        for the W, N, E and S neighbors), its entry is set to -1. */


/** Returns the maximum angular distance between a pixel center and its
      corners.
      @return maximum angular distance between a pixel center and its
        corners. */


/** Returns the z-coordinate (equivalent to the cosine of the colatitude)
      for the requested ring.
      This method also accepts the not-really-existing ring indices 0 and
      4*Nside, which correspond to North and South Poles, respectively.
      @param ring ring index: the northernmost ring in the map has index 1;
        ring indices are increasing towards the South pole.
      @return z-coordinate of the ring. */


/** Returns the colatitude for the requested ring.
      This method also accepts the not-really-existing ring indices 0 and
      4*Nside, which correspond to North and South Poles, respectively.
      @param ring ring index: the northernmost ring in the map has index 1;
        ring indices are increasing towards the South pole.
      @return z-coordinate of the ring. */


/** Returns a range set of pixels whose centers lie within a given latitude
      range (if {@code inclusive==false}), or which overlap with this range
      (if {@code inclusive==true}).

      The latitude range is defined as follows:

if {@code theta1<theta2}, it is the range between {@code theta1}
          and {@code theta2}

otherwise it is the range between 0 and {@code theta2}, and between
          {@code theta1} and pi.

      This method currently only works in the RING scheme. */


/** Compute ring index from pixel number.
      Works in both RING and NESTED schemes
      @param pix pixel number
      @return ring index (1 to 4Nside-1) */


/** Returns a set of points along the boundary of the given pixel.
    * Step 1 gives 4 points on the corners. The first point corresponds
    * to the northernmost corner, the subsequent points follow the pixel
    * boundary through west, south and east corners.
    *
    * @param pix pixel index number
    * @param step the number of returned points is 4*step
    * @return {@link Vec3} for each point
    * @throws Exception
    */


/** Normalize theta range */


/** Normalize theta and phi ranges */


/** Returns the maximum HEALPix order necessary to describe the Moc exactly.
      */


/** Returns a Moc with degraded resolution.
      @param order the maximum HEALPix order used for the result
      @param keepPartialCells if true, partially filled cells will be included
        in the output Moc; if false, they will be ignored. */


/** Adds a range of pixels at a given HEALPix order to the Moc.
      @param order the HEALPix order of the added pixels
      @param p1 the first pixel of the range
      @param p2 the one-after-last pixel of the range */


/** Returns the complement of this Moc. */


/** @return A RangeSet containing all HEALPix pixels (in NUNIQ order) covered
      by this Moc. The result is well-formed in the sense that every pixel is
      given at its lowest possible HEALPix order. */


/** @return A Moc built from the RangeSet of NUNIQ HEALPix pixels given in
      "ru". "ru" need not be well-formed. */


/** Converts the contents of a FITS input stream to a MOC. */


/** Converts the contents of a FITS file to a MOC. */


/** Writes the provided Moc to the stream in FITS format. */


/** Writes the provided Moc to the specified file in FITS format. */


/**
     * For array items, each dimension in the data array is described
     * by a corresponding scalar item. This method returns the GSDItem
     * object items associated with each dimension in the
     * data. Returns an empty array for a scalar item.
     *
     * @return An array of GSDItem object corresponding to each dimension.
     */


/**
     * Indicates whether the item is scalar or an array of values.
     *
     */


/**
     * If an array, this is the dimensionality of the data array.
     */


/**
     * If an array, this is the name of each axis.
     *
     * @return ndims strings.
     */


/**
     * If an array, this is the name of each axis, using the
     * long name of the item.
     *
     * @return ndims strings.
     */


/**
     * If an array, this is the units associated with each axis.
     *
     * @return ndims strings.
     */


/**
     * If an array, this is the item numbers associated with each axis.
     * Use the dimitems() method to return the actual items. The item
     * numbers refer to the original GSD file.
     *
     * @return ndims numbers
     */


/**
     * Return the number of data elements associated with the item.
     * Calculated from the dimensions and so does not force a read
     * of the item data (although it may force a read of the associated
     * dimensional items).
     *
     * @return the number of elements.
     */


/**
     * Print the contents of the Item to standard output. If the item
     * represents an array item the data values will only be printed
     * if the number of items is less than or equal to the specified maximum.
     * This will force a conversion of the data bytes into a native Java
     * object only if the number of elements in the object is smaller than
     * the limit.
     *
     * @param maxsize  Only print data arrays if they are smaller than this
     *                 value. A negative value indicates that the length is
     *                 dumped regardless of size.
     */


/**
     * Given a GSDItem, attempt to attach data to it. Nothing is
     * returned, the Item is modified in place. This method is called
     * automatically when the GSDItem.getData() method is invoked if
     * the data have not previously been read from file. Strings are trimmed
     * of excess spaces.
     */


/**
	 * Retrieve all the items associated with this GSD file.
	 * Note that the array returned by this method is indexed in the
	 * normal manner (starting at zero) and that this differs from the
	 * standard numbering of GSD items as used in the itemByNum() method.
	 *
	 * @return GSDItem[] array indexed from zero.
	 */


/**
	  * Return item contents by GSD item name. Item names are case
	  * insensitive. The name can be either the long name or the short
	  * name.
          *
	  * @param itemname Name of the requested item.
	  * @return a GSDItem object with all the Item information
	  * @throws GSDException if the named item is not present.
	  */


/**
	 * Return item contents by GSD item number.
	 *
	 * @param itemno The item number (starting at 1, maximum value defined
	 *               by getNumItems)
	 * @return a GSDItem object with all the Item information
	 * @throws IndexOutOfBoundsException  if the requested item number is
	 *         outside the allowed range.
	 */


/**
	 * Dump the contents of the file as text to standard out
	 * without special formatting. Equivalent to the gsdprint
	 * command.
	 */


/* I N T E R N A L   I O   R O U T I N E S */


/**
	 * For each of the no_items items in the file the next
	 * block of the buffer contains the information associated
	 * with each item but not the data itself
	 * [which is to be extracted later]. Assumes the buffer is at
	 * the correct position.
	 *
	 * @throws NullPointerException if an item describing an array
	 * dimension has not been read before the array item itself.
	 */


// Associated each item with its short and long name.


// Attach the actual data to each of the individual items


/**
     * Pads (or truncates) a string so that it is forced to be the
     * specified length. Space padded.
     *
     * @param input String to be truncated.
     * @param outputLength Length of the return string.
     * @return
     */


/**
	 * Convert 4 bytes in VAX floating point format to a Java float.
	 * This routine is a clone of gsd2_nativr in the C GSD library
	 * written by Horst Meyerdierks and Remo Tilanus.
	 *
	 * @param bytes Array of 4 bytes in VAX sequence
	 * @return IEEE float
	 */


/**
	 * Convert a VAX little-endian 4 byte sequence to a Java int.
	 *
	 * @param bytes Array of bytes representing a VAX integer.
	 * @return Java int.
	 */


/**
	 * Convert a VAX little-endian 2 byte sequence to a Java short
	 *
	 * @param bytes Array of bytes representing a VAX word.
	 * @return Java short.
	 */


/**
	 * Convert a VAX logical to a boolean.
	 *
	 * @param bytes Array of bytes representing a VAX logical
	 * @return Java boolean
	 */


/**
	 * Convert 8 bytes in VAX floating point format to a Java double.
	 * This routine is a clone of gsd2_nativd in the C GSD library
	 * written by Horst Meyerdierks and Remo Tilanus.
	 *
	 * @param bytes Array of 8 bytes in VAX sequence
	 * @return IEEE double precision float
	 */


/**
	 * Converts a Fortran-style string into a Java string.
	 * The characters in the byte array are assumed to represent
	 * the US-ASCII character set. A single byte per character.
	 *
	 * @param bytes Array of bytes assumed to represent characters. All the
	 *              bytes are converted to characters in the output string.
	 * @return Java string
	 * @throws IllegalStateException if the character set used by this
	 * routine is no longer supported by the String constructor. This
	 * should never happen (unless US-ASCII is suddenly deprecated).
	 */


/**
	 * Convert a VAX byte array into an array of booleans.
	 *
	 * @param bytes Input byte array to convert.
	 * @param offset Start position to begin reading the input bytes array.
	 * @param nelem Number of elements to copy.
	 * @return array of booleans.
	 */


/**
	 * Convert a VAX byte array into an array of shorts.
	 *
	 * @param bytes Input byte array to convert.
	 * @param offset Start position to begin reading the input bytes array.
	 * @param nelem Number of elements to copy.
	 * @return Array of shorts.
	 */


/**
	 * Convert a VAX byte array into an array of ints.
	 *
	 * @param bytes Input byte array to convert.
	 * @param offset Start position to begin reading the input bytes array.
	 * @param nelem Number of elements to copy.
	 * @return Array of ints.
	 */


/**
	 * Convert a VAX byte array into an array of floats.
	 *
	 * @param bytes Input byte array to convert.
	 * @param offset Start position to begin reading the input bytes array.
	 * @param nelem Number of elements to copy.
	 * @return Array of floats.
	 */


/**
	 * Convert a VAX byte array into an array of doubles.
	 *
	 * @param bytes Input byte array to convert.
	 * @param offset Start position to begin reading the input bytes array.
	 * @param nelem Number of elements to copy.
	 * @return Array of doubles.
	 */


/**
	 * Convert a VAX byte array into an array of strings.
	 * The strings are assumed to represent a US-ASCII character set.
	 *
	 * @param bytes Input byte array to convert.
	 * @param offset Start position to begin reading the input bytes array.
	 * @param nelem Number of elements to copy.
	 * @param nchars Size of each string in the array (in bytes).
	 * @return Array of strings.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * for each float in turn rather than creating a large intermediate
	 * array of bytes. For this reason, this method is probably slower
	 * than the byte array equivalent but will use far less memory
	 * especially if the ByteBuffer is obtained from memory mapping
	 * of a file.
	 *
	 * @param buffer An ByteBuffer containing vax bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of floats.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * for each integer in turn rather than creating a large intermediate
	 * array of bytes. For this reason, this method is probably slower
	 * than the byte array equivalent but will use far less memory
	 * especially if the ByteBuffer is obtained from memory mapping
	 * of a file.
	 *
	 * @param buffer An ByteBuffer containing vax bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of integers.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * for each short in turn rather than creating a large intermediate
	 * array of bytes. For this reason, this method is probably slower
	 * than the byte array equivalent but will use far less memory
	 * especially if the ByteBuffer is obtained from memory mapping
	 * of a file.
	 *
	 * @param buffer An ByteBuffer containing vax bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of shorts.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * for each boolean in turn rather than creating a large intermediate
	 * array of bytes. For this reason, this method is probably slower
	 * than the byte array equivalent but will use far less memory
	 * especially if the ByteBuffer is obtained from memory mapping
	 * of a file.
	 *
	 * @param buffer An ByteBuffer containing vax bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of booleans.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * for each double in turn rather than creating a large intermediate
	 * array of bytes. For this reason, this method is probably slower
	 * than the byte array equivalent but will use far less memory
	 * especially if the ByteBuffer is obtained from memory mapping
	 * of a file.
	 *
	 * @param buffer An ByteBuffer containing vax bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of doubles.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * for each string in turn rather than creating a large intermediate
	 * array of bytes. For this reason, this method is probably slower
	 * than the byte array equivalent but will use far less memory
	 * especially if the ByteBuffer is obtained from memory mapping
	 * of a file.
	 *
	 * @param buffer An ByteBuffer containing vax bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of strings.
	 */


/**
	 * This method converts bytes from a ByteBuffer rather than from
	 * an array of bytes. The bytes are extracted from the ByteBuffer
	 * and simply copied to an output array of the correct size without
	 * modification.
	 *
	 * @param buffer An ByteBuffer containing simple bytes
	 * @param offset Start position to begin reading the input buffer.
	 * @param nelem Number of elements to copy.
	 * @return An array of bytes.
	 */


/**
	 * Similar to tointArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @return Array of integers.
	 */


/**
	 * Similar to toshortArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @return Array of shorts.
	 */


/**
	 * Similar to tofloatArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @return Array of floats.
	 */


/**
	 * Similar to todoubleArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @return Array of doubles.
	 */


/**
	 * Similar to toboolArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @return Array of booleans.
	 */


/**
	 * Similar to tobyteArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @return Array of bytes.
	 */


/**
	 * Similar to tostringArray() except the length of the byte stream
	 * is specified rather than the number of elements.
	 *
	 * @param buffer A ByteBuffer containing the VAX bytes.
	 * @param offset Offset into the ByteBuffer.
	 * @param nbytes Number of bytes to read from the buffer.
	 * @param nchar  Number of characters per element
	 * @return Array of strings.
	 */


// Generic byte copy. Just a wrapper for System.arraycopy()


/**
     * Opens the named file as a PrintStream.
     * @param fn the name of the file to open
     * @param name if non-null, a message is written to System.err
     * describing the action.
     * @return an open PrintStream
     * @throws IOException if there is a problem opening the stream
     */


/**
     * Generate a Makefile go the given stream, expressing all the
     * various types of dependencies.  At its core, this just calls
     * getCompleteDependencies on each component in turn, and writes
     * those out as Makefile dependencies, but it also emits slightly
     * variant versions for buildsupport, configure and obsolete dependencies,
     * and adds various cosmetic and convenience targets.
     *
     * @param makefile an open stream to receive the makefile
     */


/**
     * Creates a list of all the dependencies in an order which
     * respects the dependencies.  That is, each (Component) element
     * in the list comes after each of the components upon which it
     * depends.
     *
     * @param dependencies a Set of Dependency objects
     * @return a List of Components, in (one possible) build order
     */


/**
     * Does a `make' on the given component, adding it to the list of
     * `make' components.  This imitates the action of make in
     * following through the chain of dependencies, but the only
     * actual action is to add the component to the build-sequence
     * list.
     *
     * @param cpt the Component to make
     * @param buildSeq the build sequence as a list, edited in place
     * (not very Functional!)
     * @param seenCpts the set of components already traversed by
     * this method
     */


/**
     * Make an XML file containing the flattened dependencies of each
     * component.  This is very similar in its logic to
     * {@link makeMakefile} -- see that routine for discussion.
     */


/**
         * Retrieves all of the components which have been allocated
         * @return an Iterator which produces each of the components
         * in turn
         */


/** Returns true if the type is one of the legal ones */


/**
         * Returns a Comparator object, which compares based only on
         * names, rather than types and options, as this class as a
         * whole does.  Thus:
         *
         *
Note This comparator imposes orderings
         * that are inconsistent with equals, since it regards
         * objects as equal when the equals() method on
         * Dependency distinguishes them.
         */


/**
     * Read Harvest configuration file
     * @param file Harvest server configuration file
     * @return configuration object
     * @throws Exception an exception
     */


/**
     * This function is called when the lambda is invoked
     *
     * @return The result of the footprint task
     */


/**
     * Footprint task executed by the Cumulus message adapter. This function wil:
     *
     * @return The input message augmented with the newly calculated footprint, and serialized as a String.
     */


/**
     * Create a directory where we dump granule file, nc file and generated footprint file
     * based on UUID.randomUUID()
     *
     * @return the path to new temporary directory
     */


/**
     * Create footprint file *.fp in working directory and upload to a environment setup
     * env_bucket_name and env_directory.   the fp file will be finally placed under
     * s3://env_bucket_name/env_directory/collection_name/granuleId.fp.
     * The fp file will then decoded and used in MetadataAggregator lambda to modify cmr.json and
     * post the new UMM-G to CMR.
     *
     * @param workingDir : the lambda/ECS working directory
     * @param collectionName : collection short name
     * @param granuleId : granule id
     * @param outJsonString: Json string including FOOTPRINT and EXTENT
     * @return the absolute path of the created fp file - if no error.
     */


/**
     * Download a file from a url
     *
     * @param url                 the base url of where to get the file
     * @param workDir             the local directory to store the dataset config file
     * @param collectionName      the name of this collection, which is the name of the dataset config file.
     * @return the absolute path of the downloaded file
     */


/**
     * Download a file from S3
     *
     * @param bucket                 the bucket the file is located in
     * @param key                    the key of the file
     * @param outputFileAbsolutePath the absolute path of where to download this S3 file to
     * @return the absolute path of the downloaded file
     */


/**
     * Upload a file to S3
     *
     * @param bucket the bucket to upload the file to
     * @param key    the key to upload to file into
     * @param file   the file to upload
     * @return The S3 URI of the uploaded file
     */


/**
     * Given a dataset config filename, generate a DatasetConfig object containing the relevant configuration values
     * for the footprint operation.
     *
     * @param configFileLocation The file path of the dataset configuration file
     * @return A DatasetConfig object which contains the configuration values from the config file.
     * @throws FileNotFoundException If the given dataset config file is not found.
     */


/**
     * Given a pattern like A:B,C:D,E:F,etc..., construct a list of NetCDF4 ranges which will be used to generate the
     * footprint for this granule.
     *
     * @param pattern A string pattern which represents what type of ranges to return, and in what order.
     * @param shapes  The size of the data, used when constructing the ranges.
     * @return A list of ranges, constructed from the given pattern and data shape.
     * @throws InvalidRangeException The function assumes the form A:B,C:D,etc. If the correct format is not provided,
     *                               this error may occur.
     */


/**
    * Checks whether the given latitude and longitude variables contain at least one valid coordinate pair.
    *
    *
The method reads the values from the provided latitude and longitude variables, applies
    * scale and offset corrections from the corresponding attribute maps, and verifies if at least
    * one coordinate pair falls within the valid geographic bounds.

    *
    * @param latVariable  The latitude variable containing raw latitude values.
    * @param lonVariable  The longitude variable containing raw longitude values.
    * @param latAttMap    A map containing the scale and offset attributes for latitude correction.
    * @param lonAttMap    A map containing the scale and offset attributes for longitude correction.
    * @param is360        A flag indicating whether the longitude range is [0, 360] (true) or [-180, 180] (false).
    * @return             {@code true} if at least one valid coordinate pair is found, otherwise {@code false}.
    * @throws IOException If reading from the variables fails.
    */


/**
     * Do the work of footprinting the NetCDF4 file.
     *
     * @return Map containing the result. This map contains the keys 'EXTENT' and 'FOOTPRINT', where 'EXTENT'
     * represents the WKT spatial bounds (a.k.a bbox) and the 'FOOTPRINT' represents the WKT footprint (might be a
     * POLYGON, LINESTRING, ...)
     */


/**
     * For the given NetCDF4 lat/lon variables, return a list of (X,Y) coordinates. 'fill' values are not part of the
     * result.
     *
     * @param rangeList List of ranges used to retrieve the coordinates from this granule.
     *                  180. This function will adjust the longitude values, so the returned coordinates will be -180
     *                   to 180.
     * @param lonVariable The longitude variable from the granule file
     * @param latVariable The latitude variable from the granule file
     * @param lonAttMap A map containing scale, offset, and fill for the longitude variable
     * @param latAttMap A map containing scale, offset, and fill for the latitude variable
     * @return Constructed list of lat/lon coordinates, masked and scaled using variable attributes.
     */


/**
     * Calculate a list of coordinates for the given ranges. The ranges will be adjusted as necessary until valid
     * coordinates are found.
     *
     * @param rangeList List of ranges used to retrieve list of coords
     * @param lonVariable The longitude variable from the granule file
     * @param latVariable The latitude variable from the granule file
     * @param lonAttMap A map containing scale, offset, and fill for the longitude variable
     * @param latAttMap A map containing scale, offset, and fill for the latitude variable
     * @return A list of lon/lat coordinates
     */


/**
     * Split a list of coordinate into separate lists of coordinates. A coordinate is split into a separate list if
     * the coordinate differs wildly from the previous coordinate. For example, if one coordinate longitude is -175,
     * and the next coordinate longitude is 175, it can be assumed that those values represent a split.
     *
     * @param coordinateList The list of coordinates to be split into multiple lists of coordinates
     * @return A list of lists of coordinates, where each list represents a split.
     */


/**
     * Find the index of the element in the given list of coordinates which is closest to the given coordinate.
     *
     * @param coordinates The list of coordinates to find the closest coordinate from.
     * @param coordinate  The coordinate to compare distance against
     * @return the integer index of the closest coordinate.
     */


/**
     * Split a list of coordinate into two separate lists at the given index, and return a list containing both lists.
     */


/**
     * When a hole has been found, merge lines to create a flat list of coordinates.
     */


/**
     * Using the merged list of coordinates representing each side of the data (sides, top, bottom), generate a Polygon
     *
     * @param coords    The merged list of coords
     * @param tolerance Tolerance to use in the simplifier algorithm.
     * @return Footprint geometry (Polygon)
     */


/**
     * Merge sides/top/bottom lists of coordinates into a single list of lists of coordinates.
     */


/**
     * Add additional coordinates to the top/bottom/sides coordinate lists, where the value at
     * that coordinate is valid.
     *
     * @throws IOException If the NetCDF Lat/Lon variables cannot be read
     */


/**
     * Apply lat and lon value to coordinate list, apply scale+offset, and
     * convert to ->360 to -180->180, if necessary.
     */


/**
     * Given a list of lists of coordinates, reverse each list.
     */


/**
     * Recursively find rows in llc which match the beginning or end of coordList. Augment coordList with those values
     * and repeat until llc is empty.
     */


/**
     * Given side(either 1 or 2)/top/bottom coordinate lists, create connected lines that will create holes in the
     * global rectangle.
     */


/**
     * Call processRemoves on the provided coordinate lists and log a warning if the result is empty.
     */


/**
     * Using the merged list of coordinates representing each side of the data (sides, top, bottom), generate a
     * Polygon or MultiPolygon.
     *
     * @param coords    The merged list of coords
     * @param tolerance Tolerance to use in the simplifier algorithm.
     * @return Footprint geometry
     */


/**
     * Find the intersection between the lists in 'removes' and the lists in 'connector', and merge those lists
     * together at the computed intersection point
     */


/**
     * Find coordinate at intersection of line1 and line2, or return null if they don't intersect.
     */


/**
     * Merge the provided coordinate lists together, but finding the intersection point of the two lists and merging.
     */


/**
     * Take 2 intersecting lines and make them one.
     */


/**
     * Because the top coords are split, update sides 1&2 and the top list with new
     * Coordinate values, creating a smooth transition between the top and sides
     *
     * @param tops   Split list of coordinates (with size > 1)
     * @param sides1 List of coordinates for side1 (any size)
     * @param sides2 List of coordinates for side2 (any size)
     */


/**
     * Because the bottom coords are split, update sides 1&2 and the bottom list with new
     * Coordinate values, creating a smooth transition between the bottom and sides
     *
     * @param bottoms Split list of coordinates (with size > 1)
     * @param sides1  List of coordinates for side1 (any size)
     * @param sides2  List of coordinates for side2 (any size)
     */


/**
     * This method takes a top or bottom cap, and the two points that attach to it, to see if there is an issue
     *
     * @param caps            Either the top or bottom cap
     * @param attachedToFirst The coordinate value attached to the first value in the top or bottom cap
     * @param attachedToLast  The coordinate value attached to the last value in the top or bottom cap
     */


/**
     * Merge top, bottom, and sides coordinate lists into a single list of coordinates.
     */


/**
     * Close polygon by adding the first point to the end of the list.
     *
     * @param coordinateList The coordinate list to close
     */


/**
     * Do additional processing in the special case where a polygon intersects both the
     * meridian and antimeridian. Normalize before continuing.
     *
     * @param geometry Geometry to possibly normalize
     * @return Geometry the normalized or unchanged geometry
     */


/**
     * Using the merged list of coordinates representing each side of the data (sides, top, bottom), generate a polygon.
     *
     * @param coords    The merged list of coords
     * @param tolerance Tolerance to use in the simplifier algorithm.
     * @return Footprint geometry
     */


/**
     * In this case, just split side1 and return. Other params are ignored.
     */


/**
     * Merge list of coordinates into a LineString geometry
     *
     * @param coords    List of coordinates used to generate geometry
     * @param tolerance Tolerance used in simplification algorithm
     * @return Computed Geometry. IN this case, will be a LineString.
     */


/**
     * Helper function used to generate coord lists
     */


/**
     * Tested java.nio.path is "/" safe when there are duplicated "/" to concatenate
     */


/**
     * Parsing a dataset config should return a DatasetConfig object containing the expected values.
     */


/**
     * Parsing a dataset config with invalid JSON (in this case, remove a curly brace) should retsult in a
     * JsonSyntaxException being thrown
     */


/**
     * Parsing a dataset config with a missing required field (in this case, latVar is missing) should result in a
     * JsonParseException exception being thrown.
     */


/**
     * Ensure a valid geometry is created from a set of manually calculated points, where side1 is split but side2
     * is not.
     */


/**
     * Ensure a valid geometry is created from a set of manually calculated points, where side1 is not split and side2
     * is.
     */


/**
     * Ensure a valid geometry is created from a set of manually calculated points, where side2 does not
     * intersect itself, but intersects tops
     */


/**
     * Merge should return the s1 side, unchanged, wrapped in another list.
     */


/**
     * mergeGeoms should generate a valid LINESTRING geometry
     */


/**
     * mergeGeoms should generate a valid MULTILINESTRING when more than one line is given in the input coordinates.
     */


/**
     * Setup mocks for testing and run calculateFootprint with the given params
     */


/**
     * Test that the FootprintStrategyPolarSmap calculateFootprint function behaves as expected, and that the side1,
     * top, and bottom Coordinate lists contain the expected values.
     */


/**
     * Test that the FootprintStrategyPolarSmap calculateFootprint function behaves as expected, and that the side1,
     * top, and bottom Coordinate lists contain the expected values.
     *
     * This case will test an example where is360 is true, so lon values above 180 should be transformed to -180/180 form
     */


/**
     * Test that the FootprintStrategyPolarSmap calculateFootprint function behaves as expected, and that the side1,
     * top, and bottom Coordinate lists contain the expected values.
     *
     * This case will test an example where removeOrigin is true, so points that are (0, 0) should not be present in
     * the result.
     */


/**
     * standard, non split polygon.
     */


/**
     * Standard split from 180 side to -180 side.
     */


/**
     * Standard split from -180 side to 180 side.
     */


/**
     * Complicated split with top and bottom being split, not the sides
     */


/**
     * Complicated split with top and bottom being split, and each side being split once
     */


/**
     * Complicated split with top being split, but not bottom, and an odd number of sides
     */


/**
     * Uneven sides, split top first is the small polygon
     */


/////////////////////////////////
// function to be minimized


/* Find the rank that has the value of MPI_MIN, or MPI_MAX.
 * If there is degeneracy, return the lower rank.
 * Avoids MPI_MINLOC and MPI_MAXLOC.
 * */


/* postfix detection, 1 if postfix is a postfix of str */


/* taken from glibc not always there. e.g. with c99. */


/* *
 * seek ptr to offset, on bb
 *
 *      offset: 0 : Start
 *              -1 : End
 *              -2 : End - 1
 *
 * returns 0
 *
 * 0 4 5 10 140
 * */


/*
 * this function will alloc memory in array and read from offset start
 * size of rows from the block.
 * free(array->data) after using it.
 *
 * at most size rows are read, array.dims[0] has the number that's read.
 *
 * if dtype is NULL use the dtype of the block.
 * otherwise cast the array to the dtype
 * */


/*Check that the passed dtype is valid.
 * Returns 1 if valid, 0 if invalid*/


/* format data in dtype to a string in buffer */


/*
 * Internal API for AttrSet objects;
 * */


/* make subdir rel to pathname, recursively making parents */


/* strdup is not in c99 */


/*
Find the Maximize DeltaT and t0.

Inputs
------

XsumP : Length P array. Contains the sum of points at every epoch
        between 0 and P-1
XcntP : Length P array. Contains the number of non-zero values that
        were summed into XcntP
P : length of XsumP and Xcnt

DelTarr : Length nDelT array. Contains the lengths of the trial
          transit durations that we will evaluate and maximize.
noiseG : Length nDelT array. Per-transit noise corresponding to each
DelTarr value.
nDelT : length of DelTarra and noiseG

Outputs
s2nMa : Maximum s2n over all epochs and widths
iMa   : Index of the DelTarr corresponding to s2nMa. [0, nDelT-1]
kMa   : Epoch corresponding to s2nMa. [0, P-1]
*/


/** Calculates \f$d^l_{mn}(\theta)\f$
         *
         * @param theta Angle in radians
         * @param l
         * @return \f$d^l_{mn}(\theta)\f$
         */


// Cache the requested azimuth expansion order if it has not already
// been calculated.


/*
 * Add a (potentially) new color to the color map.
 */


/*
 * Extract color map from a GIF file.
 */


/* Support routines for reading PPM */


/*
 * Extract color map from a PPM file.
 */


/*
 * Main entry point from djpeg.c.
 *  Input: opened input file (from file name argument on command line).
 *  Output: colormap and actual_number_of_colors fields are set in cinfo.
 */


// definitely remove this line


/*
 * Sutherland-Hodgeman algorithm sequentially clips parts outside 4 boundaries
 */


/* this routine can be used to calculate the latitude of the centroid of any grid box */


/* This routine is used to calculate the integral which equal the product of
   lontitude of the centroid and area of any grid box */


/* this routine can be used to calculate the lontitude of the centroid of any grid box */


/* This routine is used to calculate the integral which equal the product of
   latitude of the centroid and area of a uniform grid box */


/* this routine can be used to calculate the latitude of the centroid of a uniform grid box */


/* This routine is used to calculate the integral which equal the product of
   lontitude of the centroid and area of a uniform grid box */


/* this routine can be used to calculate the lontitude of the centroid of a uniform grid box */


/* Usage message for the program */


/* Close the udunits library and any open files */


/* Close an open netCDF file */


/* Convert an integer into a string with commas */


/* set if -x option is used */


/* Print the usage message for mppnccombine */


/* Open an input file and get some information about it, define the   */
/* structure of the output file if necessary, prepare to copy all the */
/* variables for the current block to memory (and non-decomposed variables */
/* will be written to the output file */


/* Decomposed variables from an input file and record will be written to memory */
/* non-decomposed variables will be written to the output file */


/* Write all the buffered decomposed variables to the output file */


/*------------------------------------------------------------------------------
  void init_river_data
  allocate memory to river data and initialize these river data with missing value
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void calc_max_subA(const river_type *river_in, river_type *river_out, int ntiles)
  find max value of suba in each model grid cell.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void update_halo_double(int ntiles, double *data, int nx, int ny, unsigned int opcode)
  We assume all the tiles have the same size.
  -----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  Find the tocell value for the new grid.
  void calc_tocell( )
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void calc_river_data()
  calculate travel and basin according to tocell, as well as celllength, cellarea.
  For each basin, one and only one river point will have tocell = 0, this point will
  have travel = 1.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void check_river_data( )
  check to make sure all the river points have been assigned travel and basin value
  and all the ocean points will have missing value.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void sort_basin(int ntiles, river_type* river_data);
  sorting the basin according to subA
  The river with larger subA at coast point will get smaller basinid.
  The basinid will be reorganized.
  -----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void write_river_data()
  write out river network output data which is on land grid.
  ----------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  double distance(double lon1, double lat1, double lon2, double lat2)
  find the distance of any two grid.
  ----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
   void do_scalar_bilinear_interp(Mosaic_config *input, Mosaic_config *output, int varid )
   interpolate scalar data to latlon,                               !
   --------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------
   void do_vector_bilinear_interp()
   interpolate vector data to latlon,                               !
   --------------------------------------------------------------------------*/


/*------------------------------------------------------------------
  void sort_index()
  sort index by shortest
  ----------------------------------------------------------------*/


/*--------------------------------------------------------------------------

calculate normalized great circle distance between v1 and v2
double normalize_great_circle_distance(v1, v2)
---------------------------------------------------------------------------*/


/*---------------------------------------------------------------------
  double dist2side(v1, v2, point)
  calculate shortest normalized distance on sphere
  from point to straight line defined by v1 and v2
  ------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void do_latlon_coarsening(var_latlon, ylat, nlon, nlat, nz,
                            var_latlon_crs, nlon_crs, nlat_crs,
                            finer_steps, misval, varmisval)

  calculate variable on coarser latlon grid
  by doubling spatial resolution and preserving volume means
  ---------------------------------------------------------------------------*/


/*------------------------------------------------------------------------------
  void redu2x(varfin, yfin, nxfin, nyfin, varcrs, nxcrs, nycrs)
  this routine is for reducing fvccm data by a factor of 2
  volume averaging for all data except at the poles
  original developer: S.-J. Lin
  ----------------------------------------------------------------------------*/


/*******************************************************************************
void init_var_config(Var_config *var)
*******************************************************************************/


/*******************************************************************************
void copy_var_config(Var_config *var)
*******************************************************************************/


/*----------------------------------------------------------------------
  void write_output_axis_data( )
  write out time axis data of the output data file
  --------------------------------------------------------------------*/


/*-------------------------------------------------------------------------
  write_field_data(Mosaic_config *output)
  write data to output file
  -----------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------
  void init_halo(double *var, int nx, int ny, int nz, int halo)
  initialze the halo data to be zero.
  ---------------------------------------------------------------------------*/


/* do_extrapolate assume the input data is on a lat-lon grid */


/*******************************************************************************
 void do_scalar_conserve_interp( )
 doing conservative interpolation
*******************************************************************************/


/*******************************************************************************
 void do_vector_conserve_interp( )
 doing conservative interpolation
*******************************************************************************/


/********************************************************************
 void full_search_nearest
 search the nearest point from the first of source grid to the last.
********************************************************************/


/*-------------------------------------------------------------------------
  void compress_double_data ()
  get global compressed data
  ------------------------------------------------------------------------*/


/*-------------------------------------------------------------------------
  void compress_int_data ()
  get global compressed data
  ------------------------------------------------------------------------*/


/***********************************************************************
   void create_vgrid(int nbnds, double *bnds, int *nz, char center, double *zeta)
   This routine is used to create vertical grid. The created grid is on super grid.
   the refinement is assumed to be 2.

   INPUT:
      nbnds:  number of vertical regions for varying resolution.
      bnds:   boundaries for defining vertical regions of varying resolution.
              The size of bnds is nz.
      nz:     Number of model grid points for each vertical regions of varying resolution.
              The size of nz will be nz-1
      center: grid cell center location. Its value can be 'N', 'T' or 'C' with default
              value 'N'. When the value is 'N', supergrid location will be calculated.
              When the value is 'T', model grid corner location will be calculated,
              other grid location of the supergrid will be derived through T-cell
              centered condition. When the value is 'C', model grid corner location will
              be calculated, other grid location of the supergrid will be derived through
              C-cell centered condition.

   OUTPUT:
      zeta:   created vertical grid location.

***********************************************************************/


/*********************************************************************
   void create_rectangular_topog()
   Constructing a rectangular basin with a flat bottom, basin_depth can be 0 ( all land).
 ********************************************************************/


/*********************************************************************
   void create_bowl_topog()
   From "Simulation of density-driven frictional downslope flow
   in z-coordinate mocean models"
   Winton et al. JPO, Vol 28, No 11, 2163-2174, November 1998
 ********************************************************************/


/*********************************************************************
   void create_gaussian_topog()
   Constructing a gaussian bump
 ********************************************************************/


/*********************************************************************

  void create_idealized_topog
   construct a highly "idealized" world ... piece by piece

   note: the purpose of this geometry/topography is to automatically
         map into arbitrary resolution as grid dimensions are
         changed, thereby facilitating the implementation
         and verification of the model on various computer platforms
         without referencing the topographic database.  Although it
         somewhat resembles the real world, it is NOT realistic.
   Note: this routine needs to be re-thought for generalized curvilinear coordinates

 ********************************************************************/


/*********************************************************************
   void create_realistic_topog( )
   reading data from source data file topog_file and remap it onto current grid
 ********************************************************************/


/*********************************************************************

    void filter_topo( int nx, int ny, int num_pass, double *depth)

       smooth topographic depth "d" with "num_pass" applications of a 2D
       version of a shapiro filter (weights = 1/4, 1/2, 1/4) .
       allow filtering to decrease the bottom depth but not increase it.
       do not allow original geometry to change.
       note: depth "d" should be on a grid of uniformly constant spacing

********************************************************************/


/* get the minimum depth of surrounding cells
   it is assumed the data ht has halo = 1
*/


/* get the minimum levels of surrounding cells
   it is assumed the data ht has halo = 1
*/


/*--- remove isolated cells */


/* Restricting partial cells, there will be no halo for data ht and kmt */


/*--- print out deepest topography */


/*********************************************************************
  void enforce_min_depth()
  ! limit the minimum value of depth, depth should be >= min_depth.
 ********************************************************************/


/******************************************************************************
void create_dome_topog(int nx, int ny, const double *x, const double *y, double dome_slope,
		       double dome_bottom, double dome_embayment_west, double dome_embayment_east,
		       double dome_embayment_south, double dome_embayment_depth, double *depth)

Construct a domain similar to the DOME configuration used in
      Legg, Hallberg, and Girton (2005) Ocean Modelling.

                         |     |
                         |     |
                        /|     |
                       / |     |
       up             /  |     |
       ^             /   |     |
       |            /    |     |
       |           /     |     |
                  /      |     |
  ---------------/-------|-----|
       --->north

*******************************************************************************/


/*-------------------------------------------------------------------*/
/* Memory copies subdomain to preallocated output pointer (either t,s,i,f,d datatype pointers).
	 Record variables should not pass in record info in the start,count,ndim,
	 so be sure to pass the pointers offset by 1 entry and ndim-1.
 */


/*-------------------------------------------------------------------*/
/* Define dimensions with optional scattering in new output files. */


/*-------------------------------------------------------------------*/
/*
In:
  isg: Start index for all tiles.
  ieg: End index for all tiles.
  ndivs: Number of tiles.

Out:
  start:  Start indices of symmetric tiling.
          Must be pre-allocated array of size ndivs.
  end:  End indices of symmetric tiling.
        Must be pre-allocated array of size ndivs.
*/


/* Returns new pointer with adjusted size. */


/**************************************************************
                     void mpp_init()
     this routine will create communicator.
***************************************************************/


/***********************************************************
               void mpp_end()
     This routine will terminate the parallel.
************************************************************/


/************************************************************
    void mpp_sync_self()
 this is to check if current PE's outstanding puts are complete
*************************************************************/


/*************************************************************
    void mpp_send_double(const double* data, int size, int to_pe)
      send data to "to_pe"
*************************************************************/


/*************************************************************
    void mpp_send_int(const int* data, int size, int to_pe)
      send data to "to_pe"
*************************************************************/


/***********************************************************
    void mpp_recv_double(double* data, int size, int from_pe)
     receive data from "from_pe"
***********************************************************/


/*******************************************************************************
  int mpp_sum_int(int count, int *data)
  sum integer over all the pes.
*******************************************************************************/


/*******************************************************************************
  void mpp_sum_double(int count, double *data)
  sum double over all the pes.
*******************************************************************************/


/***********************************************************
    void mpp_error(char *str)
    error handler: will print out error message and then abort
***********************************************************/


/*********************************************************************
    void netcdf_error( int status )
    status is the returning value of netcdf call. this routine will
    handle the error when status is not NC_NOERR.
********************************************************************/


/*************************************************************
 int mpp_open(char *filename, int action)
 open netcdf file to read or write. return the id for the file opened.
 Here the id is not the netcdf ncid of the file opened, it is the index
 in the mpp_io data files. If the file is already opened, will exit with
 an error message. For the write action, mpp_open can only be called once.
 For the read action, the file could be open and then close and then open
 again. The action should be MPP_READ, MPP_WRITE, a constant defined in
 mpp_io.h. When action is MPP_WRITE, file will be created on root pe.
************************************************************/


/* close the file */


/*********************************************************************
  int mpp_get_dimid(int fid, const char *dimname)
  get the id of the dimname from file with fid,
*********************************************************************/


/*********************************************************************
  int mpp_get_varid(int fid, const char *varname)
  get the id of the varname from file with fid, the id will be the index
  in files[fid].var.
*********************************************************************/


/********************************************************************
  int mpp_get_dimlen(char* file, char *name)
  Get the dimension.
 *******************************************************************/


/*********************************************************************
  void mpp_get_var_value(int fid, int vid, void *data)
  read part of var data, the part is defined by start and nread.
*********************************************************************/


/*********************************************************************
  void mpp_get_var_value_block(int fid, int vid, const size_t *start, const size_t *nread, void *data)
  read part of var data, the part is defined by start and nread.
*********************************************************************/


/*******************************************************************
 void mpp_get_var_att(int fid, int vid, const char *name, void *val)
 get the attribute value of vid from file fid.
 ******************************************************************/


/*******************************************************************
 void mpp_get_var_att_double(int fid, int vid, const char *name, double *val)
 get the attribute value of vid from file fid.
 ******************************************************************/


/*******************************************************************
 void mpp_get_global_att(int fid, const char *name, void *val)
 get the global attribute from file fid.
 ******************************************************************/


/********************************************************************
  nc_type mpp_get_var_type(int fid, int vid)
  get var type
********************************************************************/


/*********************************************************************
void mpp_get_var_dimname(int fid, int vid, int i, char *name)
For each dimension we are assuming there is a 1-d field have the same name as the dimension.
*********************************************************************/


/***************************************************************************
  char mpp_get_var_cart(int fid, int vid)
  get the cart of the dimension variable
  *************************************************************************/


/***************************************************************************
 void mpp_get_var_bndname(int fid, int vid, char *bndname)
 Get the bound name of dimension variable if it exist, otherwise the value will be 'none'
 for time axis, the bounds may be 'climatology'
 **************************************************************************/


/***************************************************************************
  int mpp_var_att_exist(int fid, int vid, const char *att)
  check the field var has the attribute "att" or not.
***************************************************************************/


/***************************************************************************
  int mpp_global_att_exist(int fid, const char *att)
  check  has the global attribute "att" or not.
***************************************************************************/


/*********************************************************************
  void mpp_def_global_att(int fid, const char *name, const char *val)
  write out global attribute
 ********************************************************************/


/*********************************************************************
  void mpp_def_global_att_double(int fid, const char *name, const char *val)
  write out double global attribute
 ********************************************************************/


/**********************************************************************
void mpp_def_var_att(int fid, int vid, const char *attname, const char *attval)
 define one field attribute
*********************************************************************/


/**********************************************************************
  void mpp_copy_var_att(fid_in, fid_out)
  copy all the field attribute from infile to outfile
**********************************************************************/


/**********************************************************************
  void mpp_copy_global_att(fid_in, fid_out)
  copy all the global attribute from infile to outfile
**********************************************************************/


/*********************************************************************
  void mpp_put_var_value(int fid, int vid, const void* data)
  write out string-type data

 ********************************************************************/


/*********************************************************************
  void mpp_put_var_value_block(int fid, int vid, const size_t *start, const size_t *nread, void *data)
  read part of var data, the part is defined by start and nread.
*********************************************************************/


/*********************************************************************
   void mpp_redef(int fid)
   redef the meta data of netcdf file with fid.
 *******************************************************************/


/*********************************************************************
   void mpp_end_def(int ncid)
   end the definition of netcdf file with ncid.
 *******************************************************************/


/*******************************************************************************
  int mpp_file_exist(const char *file)
  check to see if file exist or not.
*******************************************************************************/


/*********************************************************************
  double spherical_dist(double x1, double y1, double x2, double y2)
  return distance between spherical grid on the earth
*********************************************************************/


/*********************************************************************
   int lon_fix(double *x, double *y, int n_in, double tlon)
   fix longitude at pole.
 ********************************************************************/


/*********************************************************************
   void vtx_delete(double *x, double *y, int *n, int n_del)
   delete vertex
 ********************************************************************/


/*********************************************************************
   void Vtx_insert(double *x, double *y, int *n, int n_del)
   insert vertex
 ********************************************************************/


/********************************************************************************
  void compute_grid_bound(int nb, const couble *bnds, const int *npts, int *grid_size, const char *center_cell)
  compute the 1-D grid location. This algorithm is developed by Russell Fiedler
********************************************************************************/


/********************************************************************************
  void compute_grid_bound_legacy(int nb, const couble *bnds, const double *dbnds, int *grid_size, const char *center_cell)
  compute the 1-D grid location, based on the algorithm developed by Ron Pacanowski
********************************************************************************/


/************************************************************
    void mpp_define_layout()
    define domain layout based on given grid resolution and
    number of processors
***********************************************************/


/***************************************************************
 void mpp_compute_extent(int npts, int ndivs, int *ibegin, int *iend)

 Compute extent of 1-D decomposition

 problem of dividing nx points into n domains maintaining symmetry
 i.e nx=18 n=4 4554 and 5445 are solutions but 4455 is not.
 this will always work for nx even n even or odd
 this will always work for nx odd, n odd
 this will never  work for nx odd, n even: for this case we supersede the mirror calculation
 symmetrize = .NOT. ( mod(ndivs,2).EQ.0 .AND. mod(ieg-isg+1,2).EQ.1 )
 nx even n odd fails if n>nx/2

***************************************************************/


/*************************************************************
    mpp_global_field_all_double(domain2D domain, int sizex, int sizey, const double *ldata, double *gdata)
    get the global data on all the pe.
    ldata is on compute domain and gdata is on global domain
************************************************************/


/*************************************************************
    mpp_global_field_double(domain2D domain, int sizex, int sizey, const double *ldata, double *gdata)
    get the global data on root pe.
    ldata is on compute domain and gdata is on global domain
************************************************************/


/*************************************************************
    mpp_global_field_int(domain2D domain, int sizex, int sizey, const int *ldata, int *gdata)
    get the global data on root pe.
    ldata is on compute domain and gdata is on global domain
************************************************************/


/*************************************************************
    mpp_global_field_double_3D(domain2D domain, int sizex, int sizey, int sizez,
                               const double *ldata, double *gdata)
    get the global data on root pe.
    ldata is on compute domain and gdata is on global domain
************************************************************/


/*******************************************************************************
  void mpp_gather_field_int(int lsize, int *ldata, int *gdata)
  gather integer data onto every processor
*******************************************************************************/


/*******************************************************************************
  void mpp_gather_field_int_root(int lsize, int *ldata, int *gdata)
  gather integer data onto root processor
*******************************************************************************/


/*******************************************************************************
  void mpp_gather_field_double_root(int lsize, double *ldata, double *gdata)
  gather double data onto root processor
*******************************************************************************/


/*******************************************************************************
  void mpp_gather_field_double(int lsize, double *ldata, double *gdata)
  gather doubleeger data onto every processor
*******************************************************************************/


/************************************************************************************
   void create_regular_lonlat_grid( int *nxbnds, int *nybnds, double *xbnds, double *ybnds,
                                    int *nlon, int *nlat, int *isc, int *iec,
                                    int *jsc, int *jec, double *x, double *y, double *dx,
                                    double *dy, double *area, double *angle_dx, int use_great_circle_algorithm )
   calculate grid location, length, area and rotation angle.
   The routine takes the following arguments

   INPUT:

   OUTPUT:

************************************************************************************/


/************************************************************************************
   void create_simple_cartesian_grid( double *xbnds, double *ybnds, int *nlon, int *nlat,
                                      double *simple_dx, *simple_dy, int *isc, int *iec,
				      int *jsc, int *jec, double *x, double *y,
				      double *dx, double *dy, double *area, double *angle_dx )
   calculate grid location, length, area and rotation angle.
   The routine takes the following arguments

   INPUT:

   OUTPUT:

************************************************************************************/


/*******************************************************************************
   void create_spectral_grid( nt *nlon, int *nlat, int *isc, int *iec,
                              int *jsc, int *jec, double *x, double *y, double *dx,
                              double *dy, double *area, double *angle_dx )
   generate spectral horizontal grid
*******************************************************************************/


/*******************************************************************************
   void create_tripolar_grid( int int nxbnds, int nybnds, double *xbnds, double *ybnds,
                              int *nlon, int *nlat, double *lat_join_in, int *isc, int *iec,
                              int *jsc, int *jec, double *x, double *y, double *dx, double *dy,
			      double *area, double *angle_dx )
   create tripolar grid infomrmation
********************************************************************************/


/* distance between cartesian grid on the earth */


/* rectangular grid box area for cartesian grid */


/***********************************************************************
  void create_grid_from_file( char *file, int *nlon, int *nlat, double *x, double *y, double *dx,
                              double *dy, double *area, double *angle_dx )
   the grid location is defined through ascii file. calculate cell length,
   cell area and rotation angle
************************************************************************/


/*******************************************************************************
  void create_conformal_cubic_grid( int *npoints, int *nratio, char *method, char *orientation, double *x,
                          double *y, double *dx, double *dy, double *area, double *angle_dx,
                          double *angle_dy )
  create cubic grid. All six tiles grid will be generated.
*******************************************************************************/


/***********************************************************************
   calc_geoocoords_centerpole(int nx, int ny, double *x, double *y);
calculate geographic coordinates for all six tiles.

***********************************************************************/


/**********************************************************
  Convert 3-D coordinates (x,y,z) to (lon,lat)
  Assumes "lat" is positive with "z", equatorial plane
  falls at z=0  and "lon" is measured anti-clockwise (eastward)
  from x-axis (y=0) about z-axis.

************************************************************/


/**************************************************************
   void rotate_about_xaxis(int ni, int nj, double *X, double *Y,
	              	   double *Z, double angle)

   Rotate about X axis by "angle"

***************************************************************/


/*************************************************************************
   void permutetiles(int ni, int nj, double *b, int n)

   shifts the tile data left by n places around the equator
   n=1, tile 2->1, 4->2, 5->4, 1->5, the tiles 3 and 6 get rotated 90 degs.

*************************************************************************/


/*************************************************************************

     calc_fvgrid( lx, vector ly, vector dxl, vector dyl, vector areal)

     Calculates finite volume grid info (dxl,dyl,areal) for conformal cubic grid
     with 3-D coordinates (X, Y, Z)
     Meant to be used for single quadrant of tile but does work for full tile

**************************************************************************/


/*******************************************************************************
  void create_gnomonic_cubic_grid( int *npoints, int *nratio, char *method, char *orientation, double *x,
                          double *y, double *dx, double *dy, double *area, double *angle_dx,
                          double *angle_dy )
  create nomomic cubic grid. All six tiles grid will be generated.
*******************************************************************************/