private void adjustDateLineCrossingPoints() {
      ArrayList<LatLon> corners = new ArrayList<LatLon>(Arrays.asList(sw, se, nw, ne));
      if (!LatLon.locationsCrossDateLine(corners)) return;

      double lonSign = 0;
      for (LatLon corner : corners) {
        if (Math.abs(corner.getLongitude().degrees) != 180)
          lonSign = Math.signum(corner.getLongitude().degrees);
      }

      if (lonSign == 0) return;

      if (Math.abs(sw.getLongitude().degrees) == 180
          && Math.signum(sw.getLongitude().degrees) != lonSign)
        sw = new Position(sw.getLatitude(), sw.getLongitude().multiply(-1), sw.getElevation());
      if (Math.abs(se.getLongitude().degrees) == 180
          && Math.signum(se.getLongitude().degrees) != lonSign)
        se = new Position(se.getLatitude(), se.getLongitude().multiply(-1), se.getElevation());
      if (Math.abs(nw.getLongitude().degrees) == 180
          && Math.signum(nw.getLongitude().degrees) != lonSign)
        nw = new Position(nw.getLatitude(), nw.getLongitude().multiply(-1), nw.getElevation());
      if (Math.abs(ne.getLongitude().degrees) == 180
          && Math.signum(ne.getLongitude().degrees) != lonSign)
        ne = new Position(ne.getLatitude(), ne.getLongitude().multiply(-1), ne.getElevation());
    }
  /**
   * Select the visible grid elements
   *
   * @param dc the current <code>DrawContext</code>.
   */
  protected void selectRenderables(DrawContext dc) {
    if (dc == null) {
      String message = Logging.getMessage("nullValue.DrawContextIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }
    Sector vs = dc.getVisibleSector();
    OrbitView view = (OrbitView) dc.getView();
    // Compute labels offset from view center
    Position centerPos = view.getCenterPosition();
    Double pixelSizeDegrees =
        Angle.fromRadians(
                view.computePixelSizeAtDistance(view.getZoom())
                    / dc.getGlobe().getEquatorialRadius())
            .degrees;
    Double labelOffsetDegrees = pixelSizeDegrees * view.getViewport().getWidth() / 4;
    Position labelPos =
        Position.fromDegrees(
            centerPos.getLatitude().degrees - labelOffsetDegrees,
            centerPos.getLongitude().degrees - labelOffsetDegrees,
            0);
    Double labelLatDegrees = labelPos.getLatitude().normalizedLatitude().degrees;
    labelLatDegrees = Math.min(Math.max(labelLatDegrees, -76), 78);
    labelPos =
        new Position(
            Angle.fromDegrees(labelLatDegrees), labelPos.getLongitude().normalizedLongitude(), 0);

    if (vs != null) {
      for (GridElement ge : this.gridElements) {
        if (ge.isInView(dc)) {
          if (ge.renderable instanceof GeographicText) {
            GeographicText gt = (GeographicText) ge.renderable;
            if (labelPos.getLatitude().degrees < 72
                || "*32*34*36*".indexOf("*" + gt.getText() + "*") == -1) {
              // Adjust label position according to eye position
              Position pos = gt.getPosition();
              if (ge.type.equals(GridElement.TYPE_LATITUDE_LABEL))
                pos =
                    Position.fromDegrees(
                        pos.getLatitude().degrees,
                        labelPos.getLongitude().degrees,
                        pos.getElevation());
              else if (ge.type.equals(GridElement.TYPE_LONGITUDE_LABEL))
                pos =
                    Position.fromDegrees(
                        labelPos.getLatitude().degrees,
                        pos.getLongitude().degrees,
                        pos.getElevation());

              gt.setPosition(pos);
            }
          }

          this.graticuleSupport.addRenderable(ge.renderable, GRATICULE_UTM);
        }
      }
      // System.out.println("Total elements: " + count + " visible sector: " + vs);
    }
  }
    public void computeMetricScaleExtremes(
        int UTMZone, String hemisphere, GridElement ge, double size) {
      if (UTMZone != this.zone) return;
      if (size < 1 || size > this.maxResolution) return;

      UTMExtremes levelExtremes = this.extremes[(int) Math.log10(size) - 1];

      if (ge.type.equals(GridElement.TYPE_LINE_EASTING)
          || ge.type.equals(GridElement.TYPE_LINE_EAST)
          || ge.type.equals(GridElement.TYPE_LINE_WEST)) {
        levelExtremes.minX = ge.value < levelExtremes.minX ? ge.value : levelExtremes.minX;
        levelExtremes.maxX = ge.value > levelExtremes.maxX ? ge.value : levelExtremes.maxX;
      } else if (ge.type.equals(GridElement.TYPE_LINE_NORTHING)
          || ge.type.equals(GridElement.TYPE_LINE_SOUTH)
          || ge.type.equals(GridElement.TYPE_LINE_NORTH)) {
        if (hemisphere.equals(levelExtremes.minYHemisphere))
          levelExtremes.minY = ge.value < levelExtremes.minY ? ge.value : levelExtremes.minY;
        else if (hemisphere.equals(AVKey.SOUTH)) {
          levelExtremes.minY = ge.value;
          levelExtremes.minYHemisphere = hemisphere;
        }
        if (hemisphere.equals(levelExtremes.maxYHemisphere))
          levelExtremes.maxY = ge.value > levelExtremes.maxY ? ge.value : levelExtremes.maxY;
        else if (hemisphere.equals(AVKey.NORTH)) {
          levelExtremes.maxY = ge.value;
          levelExtremes.maxYHemisphere = hemisphere;
        }
      }
    }
 public void clear() {
   int numLevels = (int) Math.log10(this.maxResolution);
   this.extremes = new UTMExtremes[numLevels];
   for (int i = 0; i < numLevels; i++) {
     this.extremes[i] = new UTMExtremes();
     this.extremes[i].clear();
   }
 }
  protected ArrayList<SquareZone> createSquaresGrid(
      int UTMZone,
      String hemisphere,
      Sector UTMZoneSector,
      double minEasting,
      double maxEasting,
      double minNorthing,
      double maxNorthing) {
    ArrayList<SquareZone> squares = new ArrayList<SquareZone>();
    double startEasting = Math.floor(minEasting / ONEHT) * ONEHT;
    double startNorthing = Math.floor(minNorthing / ONEHT) * ONEHT;
    int cols = (int) Math.ceil((maxEasting - startEasting) / ONEHT);
    int rows = (int) Math.ceil((maxNorthing - startNorthing) / ONEHT);
    SquareZone[][] squaresArray = new SquareZone[rows][cols];
    int col = 0;
    for (double easting = startEasting; easting < maxEasting; easting += ONEHT) {
      int row = 0;
      for (double northing = startNorthing; northing < maxNorthing; northing += ONEHT) {
        SquareZone sz =
            new SquareZone(UTMZone, hemisphere, UTMZoneSector, easting, northing, ONEHT);
        if (sz.boundingSector != null && !sz.isOutsideGridZone()) {
          squares.add(sz);
          squaresArray[row][col] = sz;
        }
        row++;
      }
      col++;
    }

    // Keep track of neighbors
    for (col = 0; col < cols; col++) {
      for (int row = 0; row < rows; row++) {
        SquareZone sz = squaresArray[row][col];
        if (sz != null) {
          sz.setNorthNeighbor(row + 1 < rows ? squaresArray[row + 1][col] : null);
          sz.setEastNeighbor(col + 1 < cols ? squaresArray[row][col + 1] : null);
        }
      }
    }

    return squares;
  }
    public void createRenderables() {
      this.gridElements = new ArrayList<GridElement>();

      ArrayList<Position> positions = new ArrayList<Position>();
      Position p1, p2;
      Object polyline;
      Sector lineSector;

      // left segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(sw, nw, this.UTMZoneSector, positions);
      } else {
        positions.add(sw);
        positions.add(nw);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_WEST);
        ge.setValue(this.SWEasting);
        this.gridElements.add(ge);
      }

      // right segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(se, ne, this.UTMZoneSector, positions);
      } else {
        positions.add(se);
        positions.add(ne);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_EAST);
        ge.setValue(this.SWEasting + this.size);
        this.gridElements.add(ge);
      }

      // bottom segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(sw, se, this.UTMZoneSector, positions);
      } else {
        positions.add(sw);
        positions.add(se);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_SOUTH);
        ge.setValue(this.SWNorthing);
        this.gridElements.add(ge);
      }

      // top segment
      positions.clear();
      if (this.isTruncated) {
        computeTruncatedSegment(nw, ne, this.UTMZoneSector, positions);
      } else {
        positions.add(nw);
        positions.add(ne);
      }
      if (positions.size() > 0) {
        p1 = positions.get(0);
        p2 = positions.get(1);
        polyline = createLineRenderable(positions, Polyline.GREAT_CIRCLE);
        lineSector = Sector.boundingSector(p1, p2);
        GridElement ge = new GridElement(lineSector, polyline, GridElement.TYPE_LINE_NORTH);
        ge.setValue(this.SWNorthing + this.size);
        this.gridElements.add(ge);
      }

      // Label
      if (this.name != null) {
        // Only add a label to squares above some dimension
        if (this.boundingSector.getDeltaLon().degrees
                    * Math.cos(this.centroid.getLatitude().radians)
                > .2
            && this.boundingSector.getDeltaLat().degrees > .2) {
          LatLon labelPos = null;
          if (this.UTMZone != 0) // Not at poles
          {
            labelPos = this.centroid;
          } else if (this.isPositionInside(new Position(this.squareCenter, 0))) {
            labelPos = this.squareCenter;
          } else if (this.squareCenter.getLatitude().degrees
                  <= this.UTMZoneSector.getMaxLatitude().degrees
              && this.squareCenter.getLatitude().degrees
                  >= this.UTMZoneSector.getMinLatitude().degrees) {
            labelPos = this.centroid;
          }
          if (labelPos != null) {
            GeographicText text = new UserFacingText(this.name, new Position(labelPos, 0));
            text.setPriority(this.size * 10);
            this.gridElements.add(
                new GridElement(this.boundingSector, text, GridElement.TYPE_GRIDZONE_LABEL));
          }
        }
      }
    }
    public void selectRenderables(DrawContext dc) {
      try {
        OrbitView view = (OrbitView) dc.getView();
        // Compute easting and northing label offsets
        Double pixelSize = view.computePixelSizeAtDistance(view.getZoom());
        Double eastingOffset = view.getViewport().width * pixelSize * offsetFactorX / 2;
        Double northingOffset = view.getViewport().height * pixelSize * offsetFactorY / 2;
        // Derive labels center pos from the view center
        Position centerPos = view.getCenterPosition();
        double labelEasting;
        double labelNorthing;
        String labelHemisphere;
        if (this.zone > 0) {
          UTMCoord UTM =
              UTMCoord.fromLatLon(centerPos.getLatitude(), centerPos.getLongitude(), dc.getGlobe());
          labelEasting = UTM.getEasting() + eastingOffset;
          labelNorthing = UTM.getNorthing() + northingOffset;
          labelHemisphere = UTM.getHemisphere();
          if (labelNorthing < 0) {
            labelNorthing = 10e6 + labelNorthing;
            labelHemisphere = AVKey.SOUTH;
          }
        } else {
          UPSCoord UPS =
              UPSCoord.fromLatLon(centerPos.getLatitude(), centerPos.getLongitude(), dc.getGlobe());
          labelEasting = UPS.getEasting() + eastingOffset;
          labelNorthing = UPS.getNorthing() + northingOffset;
          labelHemisphere = UPS.getHemisphere();
        }

        Position labelPos;
        for (int i = 0; i < this.extremes.length; i++) {
          UTMExtremes levelExtremes = this.extremes[i];
          double gridStep = Math.pow(10, i);
          double gridStepTimesTen = gridStep * 10;
          String graticuleType = getTypeFor((int) gridStep);
          if (levelExtremes.minX <= levelExtremes.maxX) {
            // Process easting scale labels for this level
            for (double easting = levelExtremes.minX;
                easting <= levelExtremes.maxX;
                easting += gridStep) {
              // Skip multiples of ten grid steps except for last (higher) level
              if (i == this.extremes.length - 1 || easting % gridStepTimesTen != 0) {
                try {
                  labelPos = computePosition(this.zone, labelHemisphere, easting, labelNorthing);
                  if (labelPos == null) continue;
                  Angle lat = labelPos.getLatitude();
                  Angle lon = labelPos.getLongitude();
                  Vec4 surfacePoint = getSurfacePoint(dc, lat, lon);
                  if (viewFrustum.contains(surfacePoint) && isPointInRange(dc, surfacePoint)) {
                    String text = String.valueOf((int) (easting % this.scaleModulo));
                    GeographicText gt = new UserFacingText(text, new Position(lat, lon, 0));
                    gt.setPriority(gridStepTimesTen);
                    addRenderable(gt, graticuleType);
                  }
                } catch (IllegalArgumentException ignore) {
                }
              }
            }
          }
          if (!(levelExtremes.maxYHemisphere.equals(AVKey.SOUTH) && levelExtremes.maxY == 0)) {
            // Process northing scale labels for this level
            String currentHemisphere = levelExtremes.minYHemisphere;
            for (double northing = levelExtremes.minY;
                (northing <= levelExtremes.maxY)
                    || !currentHemisphere.equals(levelExtremes.maxYHemisphere);
                northing += gridStep) {
              // Skip multiples of ten grid steps except for last (higher) level
              if (i == this.extremes.length - 1 || northing % gridStepTimesTen != 0) {
                try {
                  labelPos = computePosition(this.zone, currentHemisphere, labelEasting, northing);
                  if (labelPos == null) continue;
                  Angle lat = labelPos.getLatitude();
                  Angle lon = labelPos.getLongitude();
                  Vec4 surfacePoint = getSurfacePoint(dc, lat, lon);
                  if (viewFrustum.contains(surfacePoint) && isPointInRange(dc, surfacePoint)) {
                    String text = String.valueOf((int) (northing % this.scaleModulo));
                    GeographicText gt = new UserFacingText(text, new Position(lat, lon, 0));
                    gt.setPriority(gridStepTimesTen);
                    addRenderable(gt, graticuleType);
                  }
                } catch (IllegalArgumentException ignore) {
                }

                if (!currentHemisphere.equals(levelExtremes.maxYHemisphere)
                    && northing >= 10e6 - gridStep) {
                  // Switch hemisphere
                  currentHemisphere = levelExtremes.maxYHemisphere;
                  northing = -gridStep;
                }
              }
            }
          } // end northing
        } // for levels
      } catch (IllegalArgumentException ignore) {
      }
    }