Class MilitaryGridReferenceSystem.IteratorOneZone

All Implemented Interfaces:
Spliterator<String>
Enclosing class:
MilitaryGridReferenceSystem

private final class MilitaryGridReferenceSystem.IteratorOneZone extends MilitaryGridReferenceSystem.Coder implements Spliterator<String>
Iterator over the cells in a single UTM or UPS zone. There is exactly one IteratorOneZone instance for each Universal Polar Stereographic (UPS) or Universal Transverse Mercator (UTM) projection covered by the area of interest. A given IteratorOneZone instance use the same projection for all cells.

This class extends MilitaryGridReferenceSystem.Coder in order to freeze the configuration (separator, precision, etc) to the values they have at iterator creation time, and because if we parallelize the iteration, each iterator will need its own MilitaryGridReferenceSystem.Coder.buffer, MilitaryGridReferenceSystem.Coder.normalized and MilitaryGridReferenceSystem.Coder.geographic cache.

See Also:
  • Field Details

    • areaOfInterest

      private final Rectangle2D areaOfInterest
      The region for which to return MGRS codes. This envelope can be in any CRS. This shape shall not be modified since the same instance will be shared by many IteratorOneZones.
    • gridToAOI

      private final org.opengis.referencing.operation.MathTransform2D gridToAOI
      The transform from the CRS of encoder to the CRS of areaOfInterest.
    • encoder

      private final MilitaryGridReferenceSystem.Encoder encoder
      The encoder to use for creating MGRS codes.
    • xCenter

      private final int xCenter
      The easting value of the projection natural origin. This information is used for determining whether gridX is on the left side or on right side of the center of UPS or UTM zone. We use this information for choosing the cell corner which is closest to map projection origin.
    • xEnd

      private final int xEnd
      The gridX value where to stop iteration, exclusive. This value is always greater than gridX (unless the iteration finished), but is not necessarily greater than xCenter.
    • yStart

      private int yStart
      The first northing value to use in iteration. The gridY value will need to be reset to this value for each new column.
    • yEnd

      private int yEnd
      The gridY values where to stop iteration, exclusive. Invariants:
      • gridY < yEnd shall be true in the North hemisphere, and gridY > yEnd shall be true in the South hemisphere.
      The reason of gridY relationship dependency to the hemisphere is because we try to iterate from equator to the pole.
    • gridX

      private int gridX
      Position of the next MGRS reference to encode. Position is composed of the latitude band number, the row and column indices of current 100 km square, and finally the grid coordinates inside the current 100 km square. All those components are inferred from the (easting, northing) values.
    • gridY

      private int gridY
      Position of the next MGRS reference to encode. Position is composed of the latitude band number, the row and column indices of current 100 km square, and finally the grid coordinates inside the current 100 km square. All those components are inferred from the (easting, northing) values.
    • step

      private final int step
      The amount of metres to add to gridX and to add or subtract to gridY during iteration. The sign to use when updating the gridY value depends on whether we are in the North or South hemisphere.
    • downward

      private final boolean downward
      Whether this iterator should iterates downward over rows. If true, then step shall be subtracted to gridY instead of added. We iterate downward in UTM south zones in order to go from equator to pole. This direction allows some optimizations.
    • optimize

      private final boolean optimize
      Whether this iterator is allowed to skip some cells when testing for inclusion in the area of interest. Since IteratorOneZone iterates in UTM zone from equator to pole, the range of longitude values will only decrease (the minimal longitude increase and the maximal longitude decrease). Consequently if we found a longitude out of range, we don't need to test that longitude again in next row.

      This optimization is allowed only under the following conditions:

      • areaOfInterest is a rectangle in geographic coordinates.
      • areaOfInterest does not intersect Norway and Svalbard special cases.
      • We iterate in a UTM zone, or in a UPS zone contained fully in the upper half or fully in lower half.
    • latitudeBand

      private char latitudeBand
      Latitude band of the last MGRS reference encoded by the iterator. This information is used for detecting when we moved to a new latitude band.
    • pending

      private String pending
      A MGRS reference which was pending return by tryAdvance(Consumer) before to continue iteration. This field may be non-null immediately after a change of latitude band, and should be null otherwise.
    • cell

      private final Envelope2D cell
      Temporary rectangle for computation purpose. Needs to be an implementation from the org.apache.sis.geometry in order to support AOI crossing the anti-meridian.
  • Constructor Details

    • IteratorOneZone

      IteratorOneZone(MilitaryGridReferenceSystem.Coder coder, Rectangle2D areaOfInterest, org.opengis.geometry.Envelope geographicArea, org.opengis.referencing.crs.SingleCRS sourceCRS, org.opengis.referencing.crs.ProjectedCRS targetCRS, int step) throws org.opengis.util.FactoryException, org.opengis.referencing.operation.TransformException
      Returns a new iterator for creating MGRS codes in a single UTM or UPS zone. The borders of the areaOfInterest rectangle are considered exclusive.

      For envelopes that cross the anti-meridian, it does not matter if geographicArea uses the negative width convention or is expanded to the [-180 … 180]° of longitude range, because it will be clipped to the projection domain of validity anyway. However, the areaOfInterest should use the negative width convention.

      Parameters:
      areaOfInterest - the envelope for which to return MGRS codes. This envelope can be in any CRS.
      geographicArea - the area of interest transformed into a normalized geographic CRS.
      sourceCRS - the horizontal part of the areaOfInterest CRS.
      targetCRS - the UTM or UPS projected CRS of the zone for which to create MGRS references.
      step - the amount of metres to add or subtract to grid coordinates during iteration.
      Throws:
      org.opengis.util.FactoryException
      org.opengis.referencing.operation.TransformException
    • IteratorOneZone

      private IteratorOneZone(MilitaryGridReferenceSystem.IteratorOneZone other)
      Creates an iterator for the lower half of a Universal Polar Stereographic (UPS) projection, and modifies the given iterator for restricting it to the upper half of UPS projection. This method is for trySplit() usage only.
  • Method Details

    • trySplit

      public Spliterator<String> trySplit()
      If this iterator intersects both the upper and lower half on UPS domain, returns an iterator for the lower half and modifies this iterator for the upper half. This method must be invoked before IteratorOneZone can be used.
      Specified by:
      trySplit in interface Spliterator<String>
    • estimateSize

      public long estimateSize()
      Returns an estimation of the number of cells in the area covered by this iterator. The returned value may be greater than the real amount since we do not take in account the fact that the number of cells in a row become lower as we approach poles.

      Note: returned value should be the number of remaining elements, but current implementation does not compute how many elements we have already traversed.

      Specified by:
      estimateSize in interface Spliterator<String>
    • tryAdvance

      public boolean tryAdvance(Consumer<? super String> action)
      Computes the next cell reference, if any. This method computes the bounding box in UPS or UTM coordinates, verifies if that box intersects the area of interest, and (if it intersects) delegates to MilitaryGridReferenceSystem.Encoder for creating the MGRS reference.
      Specified by:
      tryAdvance in interface Spliterator<String>
    • forEachRemaining

      public void forEachRemaining(Consumer<? super String> action)
      Performs the given action for each remaining MGRS codes.
      Specified by:
      forEachRemaining in interface Spliterator<String>
    • advance

      private boolean advance(Consumer<? super String> action, boolean all)
      Implementation of tryAdvance(Consumer) and forEachRemaining(Consumer). The all argument specifies whether this method is invoked for a single element or for all remaining ones.
    • characteristics

      public int characteristics()
      Specifies that the list of elements is immutable, that all elements will be distinct and that this iterator never return null element.
      Specified by:
      characteristics in interface Spliterator<String>
    • toString

      public String toString()
      Returns a string representation of this iterator for debugging purpose.
      Overrides:
      toString in class Object